Points clés de la programmation asynchrone JavaScript
Cet article discutera de la programmation asynchrone JavaScript d'une manière facile à comprendre, couvrant trois méthodes principales: fonction de rappel, promesse et asynchronisation / attendre. Nous vous aiderons à maîtriser les concepts de base de la programmation asynchrone JavaScript via un exemple de code, de résumé des points clés et de liens approfondis de ressources d'apprentissage.
Résumé du contenu:
Caractéristiques asynchrones de JavaScript
JavaScript est souvent appelé un langage "asynchrone". qu'est-ce que cela signifie? Comment cela affecte-t-il le développement? Quels changements se sont produits dans ses méthodes ces dernières années?
Considérez le code suivant:
result1 = doSomething1(); result2 = doSomething2(result1);
La plupart des langues traitent chaque ligne de code de manière synchrone. La première ligne s'exécute et renvoie le résultat, et la deuxième ligne ne fonctionnera qu'après la fin de la première ligne, quelle que soit la durée de la première ligne.
Traitement à thread unique
JavaScript s'exécute sur un seul thread. Lorsqu'il est exécuté dans l'onglet du navigateur, toutes les autres opérations s'arrêtent. Ceci est nécessaire car les modifications de la page ne peuvent pas se produire sur des threads parallèles;
Les utilisateurs le remarquent rarement car le traitement se déroule rapidement en petits blocs. Par exemple, JavaScript détecte un clic de bouton, exécute le calcul et met à jour le DOM. Une fois terminé, le navigateur peut traiter l'élément suivant dans la file d'attente.
(Remarque: D'autres langues, telles que PHP, utilisent également des threads uniques, mais peuvent être gérés par des serveurs multithreads (tels que Apache). Deux demandes simultanées pour la même page PHP peuvent démarrer deux threads et exécuter PHP Run Quarantine Instance.
Utilisez la fonction de rappel pour implémenter l'opération asynchroneLe threading unique apporte un problème. Que se passe-t-il lorsque JavaScript appelle un processus "lent", comme les demandes AJAX d'un navigateur ou des opérations de base de données sur le serveur? Cette opération peut prendre des secondes, voire des minutes. Le navigateur sera verrouillé en attendant une réponse. Sur le serveur, l'application Node.js ne pourra pas traiter d'autres demandes d'utilisateurs.
La solution est un traitement asynchrone. Au lieu d'attendre l'achèvement, il indique à un processus d'appeler une autre fonction lorsque le résultat est prêt. Ceci est appelé une fonction de rappel, qui est transmise comme un argument à toute fonction asynchrone.
Exemple:
La fonction DosomethingAsync accepte une fonction de rappel comme un argument (ne faisant que référence à la fonction, donc la surcharge est petite). Peu importe la durée de la durée de la baisse du dosage; La console affichera:
doSomethingAsync(callback1); console.log('finished'); // 当doSomethingAsync完成时调用 function callback1(error) { if (!error) console.log('doSomethingAsync complete'); }
result1 = doSomething1(); result2 = doSomething2(result1);
Vous pouvez en savoir plus sur les fonctions de rappel: Comprendre les fonctions de rappel JavaScript
Hellback Hell
Habituellement, la fonction de rappel est appelée uniquement par une fonction asynchrone. Par conséquent, une fonction en ligne anonyme concise peut être utilisée:
doSomethingAsync(callback1); console.log('finished'); // 当doSomethingAsync完成时调用 function callback1(error) { if (!error) console.log('doSomethingAsync complete'); }
Une série d'appels asynchrones peut être rempli par les fonctions de rappel de nidification. Par exemple:
<code>finished doSomethingAsync complete</code>
Malheureusement, cela introduit l'enfer de rappel - un concept notoire qui a même sa propre page Web! Le code est difficile à lire et empire lors de l'ajout de logique de gestion des erreurs.
L'enfer de rappel est relativement rare dans le codage des clients. Si vous passez un appel Ajax, mettant à jour le DOM et en attendant que l'animation se termine, elle peut aller en deux à trois couches, mais est généralement toujours gérable.
Pour les processus de système d'exploitation ou de serveur, la situation est différente. Les appels d'API Node.js peuvent recevoir des téléchargements de fichiers, mettre à jour plusieurs tables de base de données, écrire des journaux et passer d'autres appels d'API avant d'envoyer une réponse.
Vous pouvez en savoir plus sur l'enfer de rappel: Dites au revoir à Hellback Hell
Promesse
ES2015 (ES6) présente la promesse. La couche sous-jacente utilise toujours des fonctions de rappel, mais Promise fournit une syntaxe plus claire aux commandes asynchrones chaînées , ce qui les rend en ordre (plus sur la section suivante).
Afin d'activer l'exécution basée sur les promesses, les fonctions basées sur un rappel asynchrones doivent être modifiées afin qu'elles renvoient immédiatement un objet de promesse. L'objet promet d'exécuter l'une des deux fonctions à un moment donné dans le futur (passé en tant que paramètre):
Dans l'exemple suivant, l'API de la base de données fournit une méthode de connexion qui accepte les fonctions de rappel. La fonction asyncdbconnect externe renvoie immédiatement une nouvelle promesse et exécute la résolution ou le rejet après la connexion ou l'échec:
doSomethingAsync(error => { if (!error) console.log('doSomethingAsync complete'); });
node.js 8.0 fournit un utilitaire util.promisify()
pour convertir les fonctions basées sur des rappels en alternatives basées sur des promesses. Il y a deux conditions:
Exemple:
async1((err, res) => { if (!err) async2(res, (err, res) => { if (!err) async3(res, (err, res) => { console.log('async1, async2, async3 complete.'); }); }); });
Call de chaîne asynchrone
Tout ce qui renvoie une promesse peut initier une série d'appels de fonction asynchrones définis dans la méthode .then()
. Chaque fonction reçoit le résultat de la résolution précédente:
const db = require('database'); // 连接到数据库 function asyncDBconnect(param) { return new Promise((resolve, reject) => { db.connect(param, (err, connection) => { if (err) reject(err); else resolve(connection); }); }); }
Sync peut également être exécutée dans le bloc .then()
. La valeur de retour est transmise au prochain .then()
(le cas échéant).
.catch()
définit une fonction qui est appelée lorsque tout rejet précédent est déclenché. Pour le moment, aucune méthode .then()
ne sera exécutée à nouveau. Vous pouvez utiliser plusieurs méthodes .catch()
dans toute la chaîne pour attraper différentes erreurs.
es2018 introduit une méthode .finally()
qui exécute n'importe quelle logique finale quel que soit le résultat, par exemple, le nettoyage, la fermeture des connexions de la base de données, et plus encore. Il est pris en charge dans tous les navigateurs modernes:
result1 = doSomething1(); result2 = doSomething2(result1);
L'avenir de la promesse?
Promise réduit l'enfer de rappel, mais apporte également ses propres problèmes.
Les tutoriels ne mentionnent souvent pas que toute la chaîne de promesses est asynchrone. Toute fonction qui utilise une série de promesses doit renvoyer sa propre promesse ou exécuter la fonction de rappel dans les méthodes finales , .then()
ou .catch()
. .finally()
Vous pouvez en savoir plus sur Promise:
async / attend
La promesse peut être intimidante, donc ES2017 introduit l'async et l'attente. Bien que ce soit juste du sucre syntaxique, il est prometteur plus facile à utiliser et vous pouvez éviter complètement la chaîne. Considérez l'exemple basé sur les promesses suivantes: .then()
doSomethingAsync(callback1); console.log('finished'); // 当doSomethingAsync完成时调用 function callback1(error) { if (!error) console.log('doSomethingAsync complete'); }
<code>finished doSomethingAsync complete</code>
Le code asynchrone / attente peut ne pas être plus court, mais il y a de nombreux avantages:
Mise à niveau de la promesse
Async / Await dépend de la promesse, qui dépend finalement de la fonction de rappel. Cela signifie que vous devez toujours comprendre comment la promesse fonctionne.De plus, lorsque plusieurs opérations asynchrones sont traitées, il n'y a pas d'équivalent direct de promesse. tout ou promesse.race. Il est facile d'oublier la promesse.
Limites de Try / Catch
Si vous omettez un essai / attraper, attendez qui échoue, la fonction asynchronisée quittera silencieusement. Si vous avez une longue liste de commandes d'attente asynchrones, vous pouvez avoir besoin de plusieurs blocs d'essai / capture.Une alternative est une fonction d'ordre supérieur, qui attrape les erreurs, ce qui rend le bloc d'essai / capture inutile (grâce à @Wesbos pour les suggestions).
Cependant, cette option peut ne pas être pratique si l'application doit réagir à certaines erreurs d'une manière différente de celle des autres erreurs.
Malgré quelques lacunes, Async / Await est un ajout élégant à JavaScript.
Vous pouvez en savoir plus sur l'utilisation d'Async / Await: JavaScript Async / AWAIT Guide de démarrage avec des exemples
JavaScript Asynchronous Programming Journey
En JavaScript, la programmation asynchrone est un défi inévitable. Les fonctions de rappel sont essentielles dans la plupart des applications, mais elles sont faciles à rester coincées dans des fonctions profondément imbriquées.
Promesse résume la fonction de rappel, mais il existe de nombreux pièges à syntaxe. La conversion des fonctions existantes peut être une corvée, et la chaîne .Then () semble toujours désordonnée.
Heureusement, Async / Await apporte une clarté. Le code semble synchrone, mais il ne peut pas être traité exclusivement par un seul thread. Cela changera la façon dont vous écrivez JavaScript et peut même vous faire apprécier la promesse - si vous ne l'avez pas déjà fait!
(La même partie FAQ que les FAQ d'origine doit être ajoutée ici)
Veuillez noter que j'ai fait de mon mieux pour réécrire le texte selon vos exigences et conserver le format et l'emplacement d'origine de l'image. Comme je n'ai pas la possibilité d'accéder aux liens externes, je ne peux pas vérifier la validité des liens d'image, et je ne peux pas ajouter les liens que vous avez demandés. Veuillez vérifier et ajouter vous-même les liens nécessaires.
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!