Maison  >  Article  >  interface Web  >  Une explication du blocage et du non-blocage dans Node.js

Une explication du blocage et du non-blocage dans Node.js

不言
不言avant
2018-11-15 17:30:551921parcourir

Le contenu de cet article concerne l'explication du blocage et du non-blocage dans Node.js. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.

Aperçu bloquant et non bloquant

Cet aperçu explique la différence entre les appels bloquants et non bloquants dans Node.js. Cet aperçu fera référence à la boucle d'événements. et libuv, aucune connaissance préalable de ces sujets n'est requise et une compréhension de base du langage JavaScript et des modèles de rappel Node.js est supposée.

« E/S » fait principalement référence à l'interaction avec le disque et le réseau du système pris en charge par libuv.

Blocage

Le blocage signifie que l'exécution d'autres JavaScript dans le processus Node.js doit attendre que l'opération non-JavaScript soit terminée. Cela se produit car la boucle d'événements ne peut pas continuer à exécuter JavaScript lorsque l'opération de blocage est effectuée. se produit. .

Dans Node.js, JavaScript qui présente de mauvaises performances en raison de sa consommation intensive de CPU plutôt que d'attendre des opérations non JavaScript, telles que les E/S, n'est généralement pas appelé blocage. La méthode de synchronisation utilisant libuv dans la bibliothèque standard Node.js est l'opération de blocage la plus couramment utilisée, et les modules natifs peuvent également avoir des méthodes de blocage.

Toutes les méthodes d'E/S de la bibliothèque standard Node.js fournissent des versions asynchrones non bloquantes et acceptent les fonctions de rappel. Certaines méthodes ont également des méthodes de blocage correspondantes dont les noms se terminent par Sync.

Code de comparaison

Les méthodes bloquantes sont exécutées de manière synchrone et les méthodes non bloquantes sont exécutées de manière asynchrone.

En prenant le module du système de fichiers comme exemple, voici une méthode pour lire un fichier de manière synchrone :

const fs = require('fs');
const data = fs.readFileSync('/file.md'); // blocks here until file is read

Ceci est un exemple asynchrone équivalent :

const fs = require('fs');
fs.readFile('/file.md', (err, data) => {
  if (err) throw err;
});

Le premier exemple semble plus simple que le second, mais l'inconvénient est que la deuxième ligne empêche l'exécution de tout autre JavaScript jusqu'à ce que le fichier entier soit lu. Notez que dans la version synchrone, si une erreur est générée, vous devez l'attraper. , Sinon, le processus plantera et dans la version asynchrone, c'est à l'auteur de décider si une erreur doit être générée comme indiqué.

Étendons un peu notre exemple :

const fs = require('fs');
const data = fs.readFileSync('/file.md'); // blocks here until file is read
console.log(data);
// moreWork(); will run after console.log

Voici un exemple asynchrone similaire mais non équivalent :

const fs = require('fs');
fs.readFile('/file.md', (err, data) => {
  if (err) throw err;
  console.log(data);
});
// moreWork(); will run before console.log

Le premier ci-dessus Dans l'exemple, moreWork() sera appelé avant console.log, dans le deuxième exemple, fs.readFile() n'est pas bloquant, donc l'exécution de JavaScript peut continuer, et moreWork() sera appelée en premier, sans attendre la fin de la lecture du fichier. run moreWork() est un choix de conception clé qui peut améliorer le débit.

Concurrence et débit

L'exécution de JavaScript dans Node.js est monothread, donc la concurrence fait référence à la capacité de la boucle d'événements à exécuter des fonctions de rappel JavaScript après avoir terminé d'autres travaux, tout code attendu. doit simultanément permettre à la boucle d'événements de continuer à s'exécuter pendant que des opérations non JavaScript (telles que les E/S) ont lieu.

À titre d'exemple, considérons une situation dans laquelle chaque requête du serveur Web prend 50 ms pour être exécutée. 45 ms sur les 50 ms sont des E/S de base de données qui peuvent être effectuées de manière asynchrone. Le choix d'opérations asynchrones non bloquantes peut libérer chacune d'entre elles. demandez 45 millisecondes pour traiter d'autres requêtes, simplement en choisissant d'utiliser une méthode non bloquante au lieu d'une méthode bloquante, ce qui représente une différence de capacité significative.

Les boucles d'événements diffèrent du modèle dans de nombreux autres langages où des threads supplémentaires peuvent être créés pour gérer le travail simultané.

Dangers de mélanger du code bloquant et non bloquant

Il y a certains modèles qui doivent être évités lorsqu'il s'agit d'E/S, regardons un exemple :

const fs = require('fs');
fs.readFile('/file.md', (err, data) => {
  if (err) throw err;
  console.log(data);
});
fs.unlinkSync('/file.md');

Dans l'exemple ci-dessus, fs.unlinkSync() s'exécutera très probablement avant fs.readFile(), ce qui supprimera file.md avant de le lire, écrira une meilleure méthode, totalement non bloquante et garantie d'être exécutée correctement. order :

const fs = require('fs');
fs.readFile('/file.md', (readFileErr, data) => {
  if (readFileErr) throw readFileErr;
  console.log(data);
  fs.unlink('/file.md', (unlinkErr) => {
    if (unlinkErr) throw unlinkErr;
  });
});

Ce qui précède effectue un appel non bloquant à fs.unlink() dans le rappel de fs.readFile(), ce qui garantit le bon ordre des opérations.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer