Maison interface Web js tutoriel Analyse des rappels et des modèles de conception de code dans Node.js programmation asynchrone_node.js

Analyse des rappels et des modèles de conception de code dans Node.js programmation asynchrone_node.js

May 16, 2016 pm 03:15 PM
node 回调 异步

Le principal argument de vente de NodeJS - le mécanisme d'événements et les E/S asynchrones, ne sont pas transparents pour les développeurs. Les développeurs doivent écrire du code de manière asynchrone pour tirer parti de cet argument de vente, qui a été critiqué par certains opposants à NodeJS. Quoi qu’il en soit, la programmation asynchrone est effectivement la plus grande fonctionnalité de NodeJS. Sans maîtriser la programmation asynchrone, vous ne pouvez pas dire que vous avez vraiment appris NodeJS. Ce chapitre présentera diverses connaissances liées à la programmation asynchrone.

Dans le code, la manifestation directe de la programmation asynchrone sont les rappels. La programmation asynchrone repose sur des rappels, mais on ne peut pas dire que le programme devient asynchrone après avoir utilisé des rappels. Nous pouvons d’abord regarder le code suivant.

function heavyCompute(n, callback) {
 var count = 0,
  i, j;

 for (i = n; i > 0; --i) {
  for (j = n; j > 0; --j) {
   count += 1;
  }
 }

 callback(count);
}

heavyCompute(10000, function (count) {
 console.log(count);
});

console.log('hello');

Copier après la connexion
100000000
hello
Copier après la connexion

Comme vous pouvez le voir, la fonction de rappel dans le code ci-dessus est toujours exécutée avant le code suivant. JS lui-même s'exécute dans un seul thread, et il est impossible d'exécuter un autre code avant la fin de l'exécution d'un morceau de code, il n'y a donc pas de concept d'exécution asynchrone.

Cependant, si une fonction crée un autre thread ou processus, fait quelque chose en parallèle avec le thread principal JS et avertit le thread principal JS lorsque la chose est terminée, alors la situation est différente. Jetons un coup d'œil au code suivant.

setTimeout(function () {
 console.log('world');
}, 1000);

console.log('hello');

Copier après la connexion
hello
world
Copier après la connexion


Cette fois, vous pouvez voir que la fonction de rappel est exécutée après le code suivant. Comme mentionné ci-dessus, JS lui-même est monothread et ne peut pas être exécuté de manière asynchrone. Par conséquent, nous pouvons penser que les fonctions spéciales fournies par l'environnement d'exécution en dehors des spécifications JS telles que setTimeout sont de créer un thread parallèle et de revenir immédiatement, permettant ainsi. Maître JS vers Le processus peut ensuite exécuter le code suivant et exécuter la fonction de rappel après avoir reçu une notification du processus parallèle. En plus des fonctions courantes telles que setTimeout et setInterval, ces fonctions incluent également des API asynchrones fournies par NodeJS telles que fs.readFile.

De plus, nous revenons toujours au fait que JS s'exécute dans un seul thread, ce qui détermine que JS ne peut pas exécuter d'autres codes, y compris des fonctions de rappel, avant d'exécuter un morceau de code. En d'autres termes, même si le thread parallèle termine son travail et demande au thread principal JS d'exécuter la fonction de rappel, la fonction de rappel ne démarrera pas l'exécution tant que le thread principal JS ne sera pas inactif. Ce qui suit est un tel exemple.

function heavyCompute(n) {
 var count = 0,
  i, j;

 for (i = n; i > 0; --i) {
  for (j = n; j > 0; --j) {
   count += 1;
  }
 }
}

var t = new Date();

setTimeout(function () {
 console.log(new Date() - t);
}, 1000);

heavyCompute(50000);

Copier après la connexion
8520
Copier après la connexion


Comme vous pouvez le constater, le temps d'exécution réel de la fonction de rappel qui était censée être appelée après 1 seconde a été considérablement retardé car le thread principal JS était occupé à exécuter un autre code.

Modèles de conception de code
La programmation asynchrone comporte de nombreux modèles de conception de code uniques. Afin d'obtenir la même fonction, le code écrit en mode synchrone et en mode asynchrone sera très différent. Certains modèles courants sont présentés ci-dessous.

Valeur de retour de la fonction
Il est très courant d'utiliser la sortie d'une fonction comme entrée d'une autre fonction. En mode synchrone, le code s'écrit généralement comme suit :

var output = fn1(fn2('input'));
// Do something.
Copier après la connexion

En mode asynchrone, puisque le résultat de l'exécution de la fonction n'est pas transmis via la valeur de retour, mais via la fonction de rappel, le code est généralement écrit de la manière suivante :

fn2('input', function (output2) {
 fn1(output2, function (output1) {
  // Do something.
 });
});
Copier après la connexion

Comme vous pouvez le voir, cette méthode est une fonction de rappel imbriquée dans une seule fonction de rappel. S'il y en a trop, il est facile d'écrire du code en forme de >.

Parcourir le tableau
Lors du parcours d'un tableau, il est également courant d'utiliser une fonction pour effectuer un traitement sur les données membres en séquence. Si la fonction est exécutée de manière synchrone, le code suivant sera généralement écrit :

var len = arr.length,
 i = 0;

for (; i < len; ++i) {
 arr[i] = sync(arr[i]);
}

// All array items have processed.

Copier après la connexion

Si la fonction est exécutée de manière asynchrone, le code ci-dessus ne peut pas garantir que tous les membres du tableau ont été traités après la fin de la boucle. Si les membres du tableau doivent être traités en série les uns après les autres, le code asynchrone est généralement écrit comme suit :

(function next(i, len, callback) {
 if (i < len) {
  async(arr[i], function (value) {
   arr[i] = value;
   next(i + 1, len, callback);
  });
 } else {
  callback();
 }
}(0, arr.length, function () {
 // All array items have processed.
}));
Copier après la connexion

Comme vous pouvez le voir, le code ci-dessus ne transmet que le membre suivant du tableau et démarre le prochain cycle d'exécution après que la fonction asynchrone soit exécutée une fois et renvoie le résultat de l'exécution jusqu'à ce que tous les membres du tableau soient traités, l'exécution du code suivant. est déclenché par des rappels.

Si les membres du tableau peuvent être traités en parallèle, mais que le code ultérieur nécessite toujours que tous les membres du tableau soient traités avant de pouvoir être exécutés, le code asynchrone sera ajusté sous la forme suivante :

(function (i, len, count, callback) {
 for (; i < len; ++i) {
  (function (i) {
   async(arr[i], function (value) {
    arr[i] = value;
    if (++count === len) {
     callback();
    }
   });
  }(i));
 }
}(0, arr.length, 0, function () {
 // All array items have processed.
}));
Copier après la connexion

Comme vous pouvez le voir, par rapport à la version de parcours série asynchrone, le code ci-dessus traite tous les membres du tableau en parallèle et utilise la variable counter pour déterminer quand tous les membres du tableau ont été traités.

Gestion des exceptions
Le mécanisme de capture et de gestion des exceptions fourni par JS lui-même - try..catch.., ne peut être utilisé que pour du code exécuté de manière synchrone. Ci-dessous un exemple.

function sync(fn) {
 return fn();
}

try {
 sync(null);
 // Do something.
} catch (err) {
 console.log('Error: %s', err.message);
}

Copier après la connexion
Error: object is not a function
Copier après la connexion
Copier après la connexion

Comme vous pouvez le voir, l'exception bouillonnera le long du chemin d'exécution du code jusqu'à ce qu'elle soit interceptée lorsqu'elle rencontrera la première instruction try. Cependant, étant donné que les fonctions asynchrones interrompent le chemin d'exécution du code, lorsque les exceptions générées pendant et après l'exécution de la fonction asynchrone remontent jusqu'à l'emplacement où le chemin d'exécution est interrompu, si aucune instruction try n'est rencontrée, elles seront levées comme une exception globale. . Ci-dessous un exemple.

function async(fn, callback) {
 // Code execution path breaks here.
 setTimeout(function () {
  callback(fn());
 }, 0);
}

try {
 async(null, function (data) {
  // Do something.
 });
} catch (err) {
 console.log('Error: %s', err.message);
}

Copier après la connexion
/home/user/test.js:4
  callback(fn());
     ^
TypeError: object is not a function
 at null._onTimeout (/home/user/test.js:4:13)
 at Timer.listOnTimeout [as ontimeout] (timers.js:110:15)
Copier après la connexion

因为代码执行路径被打断了,我们就需要在异常冒泡到断点之前用 try 语句把异常捕获住,并通过回调函数传递被捕获的异常。于是我们可以像下边这样改造上边的例子。

function async(fn, callback) {
 // Code execution path breaks here.
 setTimeout(function () {
  try {
   callback(null, fn());
  } catch (err) {
   callback(err);
  }
 }, 0);
}

async(null, function (err, data) {
 if (err) {
  console.log('Error: %s', err.message);
 } else {
  // Do something.
 }
});

Copier après la connexion
Error: object is not a function
Copier après la connexion
Copier après la connexion

可以看到,异常再次被捕获住了。在 NodeJS 中,几乎所有异步 API 都按照以上方式设计,回调函数中第一个参数都是 err。因此我们在编写自己的异步函数时,也可以按照这种方式来处理异常,与 NodeJS 的设计风格保持一致。

有了异常处理方式后,我们接着可以想一想一般我们是怎么写代码的。基本上,我们的代码都是做一些事情,然后调用一个函数,然后再做一些事情,然后再调用一个函数,如此循环。如果我们写的是同步代码,只需要在代码入口点写一个 try 语句就能捕获所有冒泡上来的异常,示例如下。

function main() {
 // Do something.
 syncA();
 // Do something.
 syncB();
 // Do something.
 syncC();
}

try {
 main();
} catch (err) {
 // Deal with exception.
}

Copier après la connexion

但是,如果我们写的是异步代码,就只有呵呵了。由于每次异步函数调用都会打断代码执行路径,只能通过回调函数来传递异常,于是我们就需要在每个回调函数里判断是否有异常发生,于是只用三次异步函数调用,就会产生下边这种代码。

function main(callback) {
 // Do something.
 asyncA(function (err, data) {
  if (err) {
   callback(err);
  } else {
   // Do something
   asyncB(function (err, data) {
    if (err) {
     callback(err);
    } else {
     // Do something
     asyncC(function (err, data) {
      if (err) {
       callback(err);
      } else {
       // Do something
       callback(null);
      }
     });
    }
   });
  }
 });
}

main(function (err) {
 if (err) {
  // Deal with exception.
 }
});

Copier après la connexion

可以看到,回调函数已经让代码变得复杂了,而异步方式下对异常的处理更加剧了代码的复杂度。

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
2 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Meilleurs paramètres graphiques
2 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Comment réparer l'audio si vous n'entendez personne
2 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Comment utiliser Express pour gérer le téléchargement de fichiers dans un projet de nœud Comment utiliser Express pour gérer le téléchargement de fichiers dans un projet de nœud Mar 28, 2023 pm 07:28 PM

Comment gérer le téléchargement de fichiers ? L'article suivant vous expliquera comment utiliser Express pour gérer les téléchargements de fichiers dans le projet de nœud. J'espère qu'il vous sera utile !

Une analyse approfondie de l'outil de gestion de processus de Node « pm2 » Une analyse approfondie de l'outil de gestion de processus de Node « pm2 » Apr 03, 2023 pm 06:02 PM

Cet article partagera avec vous l'outil de gestion de processus de Node "pm2" et expliquera pourquoi pm2 est nécessaire, comment installer et utiliser pm2, j'espère qu'il sera utile à tout le monde !

Enseignement du nœud PI: Qu'est-ce qu'un nœud PI? Comment installer et configurer le nœud PI? Enseignement du nœud PI: Qu'est-ce qu'un nœud PI? Comment installer et configurer le nœud PI? Mar 05, 2025 pm 05:57 PM

Explication détaillée et guide d'installation pour les nœuds de pignon Cet article introduira l'écosystème de pignon en détail - nœuds PI, un rôle clé dans l'écosystème de pignon et fournir des étapes complètes pour l'installation et la configuration. Après le lancement du réseau de test de la blockchain pèse, les nœuds PI sont devenus une partie importante de nombreux pionniers participant activement aux tests, se préparant à la prochaine version du réseau principal. Si vous ne connaissez pas encore Pinetwork, veuillez vous référer à ce qu'est Picoin? Quel est le prix de l'inscription? PI Utilisation, exploitation minière et sécurité. Qu'est-ce que Pinetwork? Le projet Pinetwork a commencé en 2019 et possède sa pièce exclusive de crypto-monnaie PI. Le projet vise à en créer un que tout le monde peut participer

Application rapide : analyse de cas de développement pratique du téléchargement HTTP asynchrone PHP de plusieurs fichiers Application rapide : analyse de cas de développement pratique du téléchargement HTTP asynchrone PHP de plusieurs fichiers Sep 12, 2023 pm 01:15 PM

Application rapide : analyse de cas de développement pratique de PHP Téléchargement HTTP asynchrone de plusieurs fichiers Avec le développement d'Internet, la fonction de téléchargement de fichiers est devenue l'un des besoins fondamentaux de nombreux sites Web et applications. Pour les scénarios dans lesquels plusieurs fichiers doivent être téléchargés en même temps, la méthode de téléchargement synchrone traditionnelle est souvent inefficace et prend du temps. Pour cette raison, utiliser PHP pour télécharger plusieurs fichiers de manière asynchrone via HTTP est devenu une solution de plus en plus courante. Cet article analysera en détail comment utiliser le HTTP asynchrone PHP à travers un cas de développement réel.

Comment Swoole prend en charge les opérations SMTP asynchrones Comment Swoole prend en charge les opérations SMTP asynchrones Jun 25, 2023 pm 12:24 PM

Avec le développement et la vulgarisation continus d'Internet, le courrier électronique est devenu un élément indispensable de la vie et du travail des gens, et SMTP (Simple Mail Transfer Protocol) est l'un des protocoles importants pour l'envoi de courrier électronique. En tant que framework de communication réseau asynchrone pour PHP, Swoole peut bien prendre en charge les opérations SMTP asynchrones, rendant l'envoi d'e-mails plus efficace et plus stable. Cet article présentera comment Swoole prend en charge les opérations SMTP asynchrones, notamment l'utilisation

Authentification basée sur des jetons avec Angular et Node Authentification basée sur des jetons avec Angular et Node Sep 01, 2023 pm 02:01 PM

L'authentification est l'une des parties les plus importantes de toute application Web. Ce didacticiel traite des systèmes d'authentification basés sur des jetons et de leurs différences par rapport aux systèmes de connexion traditionnels. À la fin de ce didacticiel, vous verrez une démo entièrement fonctionnelle écrite en Angular et Node.js. Systèmes d'authentification traditionnels Avant de passer aux systèmes d'authentification basés sur des jetons, examinons les systèmes d'authentification traditionnels. L'utilisateur fournit son nom d'utilisateur et son mot de passe dans le formulaire de connexion et clique sur Connexion. Après avoir effectué la demande, authentifiez l'utilisateur sur le backend en interrogeant la base de données. Si la demande est valide, une session est créée à l'aide des informations utilisateur obtenues à partir de la base de données et les informations de session sont renvoyées dans l'en-tête de réponse afin que l'ID de session soit stocké dans le navigateur. Donne accès aux applications soumises à

Robot ETF (562500) pourrait ouvrir la voie à une bonne opportunité de mise en page car il a reculé pendant 3 jours consécutifs ! Robot ETF (562500) pourrait ouvrir la voie à une bonne opportunité de mise en page car il a reculé pendant 3 jours consécutifs ! Dec 01, 2023 pm 04:01 PM

En début de séance le 1er décembre 2023, les trois principaux indices boursiers ont ouvert en baisse. L'ETF Robot (562500) a commencé à s'échanger latéralement après avoir chuté en début de séance. À 10h20, l'ETF Robot (562500) a chuté de 0,92%, avec plus de 60 des 82 titres en baisse. Daheng Technology et Shitou Technology ont chuté de plus de 5 %, et Sukron Technology, Keda Intelligence, Xianhui Technology et Hongxun Technology ont chuté de plus de 3 %. Dès le début des échanges aujourd'hui, l'ETF Robot (562500) a connu une correction pendant trois jours consécutifs. En regardant la situation du mois dernier, l'ETF Robot (562500) n'a connu qu'une seule correction pendant trois jours consécutifs, puis a inauguré huit tendances positives consécutives. Ce retrait pourrait constituer une bonne opportunité de mise en page suite à l'annonce faite par les départements concernés début novembre.

Guide avancé de Python asyncio : du débutant à l'expert Guide avancé de Python asyncio : du débutant à l'expert Mar 04, 2024 am 09:43 AM

Programmation simultanée et asynchrone La programmation simultanée traite de plusieurs tâches s'exécutant simultanément, la programmation asynchrone est un type de programmation simultanée dans laquelle les tâches ne bloquent pas les threads. asyncio est une bibliothèque de programmation asynchrone en python, qui permet aux programmes d'effectuer des opérations d'E/S sans bloquer le thread principal. Boucle d'événements Le cœur d'asyncio est la boucle d'événements, qui surveille les événements d'E/S et planifie les tâches correspondantes. Lorsqu'une coroutine est prête, la boucle d'événements l'exécute jusqu'à ce qu'elle attende les opérations d'E/S. Il met ensuite la coroutine en pause et continue d'exécuter d'autres coroutines. Coroutines Les coroutines sont des fonctions qui peuvent suspendre et reprendre l'exécution. Le mot-clé asyncdef est utilisé pour créer des coroutines. La coroutine utilise le mot-clé wait pour attendre la fin de l'opération d'E/S. Les bases suivantes d'asyncio

See all articles