brève introduction
JavaScript ES7 dans la promesse async / vous attendent pour faire de multiples collaboration asynchrone plus facile à travailler ensemble. Si, selon un certain ordre pour obtenir des données à partir de plusieurs bases de données ou API asynchrone, vous pourriez jouer avec un tas de promesses et d'une fonction de rappel terminée. Le async / Attendent let structure nous utilisons un code lisible, maintenable plus succinctement permet cette logique.
Cet exemple simple tutoriel d'un graphique et expliqué en JavaScript async / Attendent syntaxe et la sémantique.
Avant de plonger dans, le bref rappel de la promesse let. Si vous connaissez déjà la promesse de JS, vous pouvez sauter cette section.
promesses
En JavaScript, la promesse au nom de la non-blocage de l'exécution asynchrone d'abstraction. Si vous connaissez Java Future, C # la tâche, vous constaterez que promettent beaucoup comme eux.
Promise pour le réseau général et des opérations d'E / S, telles que la lecture du fichier, ou de créer des requêtes HTTP. Nous pouvons créer une promesse asynchrone, puis ensuite ajouter une fonction de rappel, lorsque la fin de la promesse déclenchera la fonction de rappel, et le non-blocage de courant sous tension « fil. » La fonction de rappel lui-même peut également renvoyer un objet de la promesse, afin que nous puissions appeler la promesse de la chaîne.
Par souci de simplicité, nous supposons que tous les exemples suivants ont été installés et la bibliothèque demande-promesse chargée comme ceci:
= Var rp besoin ( 'demande-promesse');
Maintenant, nous pouvons créer un objet de promesse de retour comme simple requête HTTP GET:
const promesse = rp ( '
Nous attendons maintenant un exemple:
console.log ( 'Démarrage exécution');
const promesse = rp ( '
promise.then (résultat = > console.log (suite));
console.log ( « Peut sais pas si la promesse n'a pas encore fini ... »);
Nous avons créé un objet de promesse sur la ligne 3, ligne 4, pour lui donner ajouté une fonction de rappel. Promesse est asynchrone, lorsque la mise en uvre de la sixième ligne, nous ne savons pas si la promesse a été achevée. Si cette section de code exécuter plusieurs fois, vous pouvez obtenir des résultats différents à chaque fois. D'une manière générale, qui est la promesse et la promesse de créer un code qui est en cours d'exécution simultanément.
Jusqu'à promesse exécutée, seule façon de bloquer la séquence actuelle des opérations. Cela diffère de la Future.get de Java, il nous permet de bloquer le thread courant avant la fin de l'avenir. Pour JavaScript, nous ne pouvons pas attendre la promesse exécutée. Dans la méthode de la promesse est à l'origine du code de programme ajouté à par la fonction de rappel alors.
Le présent mode de réalisation est décrit dans la figure processus de calcul:
Promesse de calcul. « Discussion » est en cours d'exécution ne peut pas attendre la promesse d'achever la mise en uvre. Dans la méthode de la promesse est à l'origine du code de programme ajouté à par la fonction de rappel alors.
Par puis ajouter la fonction de rappel avec succès que si la promesse sera réalisée. Si elle échoue (par exemple en raison d'une erreur de réseau), la fonction de rappel ne sera pas exécutée. Vous pouvez attraper puis ajouter une fonction de rappel pour gérer la promesse a échoué:
rp ( '
puis (() = > console.log ( 'succès')).
= De capture (e > console.log ( `a échoué: $ {e}`))
Enfin, pour tester, nous pouvons utiliser Promise.resolve Promise.reject facilement créer et exécuter le succès ou l'échec de la promesse « fou »:
const = succès Promise.resolve ( 'Résolu');
// print « Résultat réussi: Résolu »
succès.
puis (résultat = > console.log ( `résultat avec succès: $ {résultat}`)).
= De capture (e > console.log ( `a échoué avec: $ {e}`))
const = Promise.reject sûr ( 'Err');
// print "Échec avec: Err"
échec.
puis (résultat = > console.log ( `résultat avec succès: $ {résultat}`)).
= De capture (e > console.log ( `a échoué avec: $ {e}`))
Pour un tutoriel promesse plus détaillé, vous pouvez vous référer à cet article.
La question est - une combinaison de promesses
Une seule promesse très facile à obtenir. Cependant, lorsque le temps nécessaire pour la programmation complexe logique asynchrone, nous sommes susceptibles de durer un certain temps avec la promesse de plusieurs objets. Ensuite, écrivez un tas de déclarations et de rappel anonyme facilement rendu difficile à contrôler.
Par exemple, supposons que nous devons résoudre les exigences du programme suivant:
Créer requête HTTP, dans l'attente des demandes et imprimer le résultat final;
Créer deux requêtes HTTP parallèles;
Après que les deux demandes, etc., d'imprimer les résultats.
Le code suivant montre comment résoudre ce problème:
// premier appel
const call1Promise = rp ( '
call1Promise.then (result1 = > {
// La première demande est terminée est exécutée
console.log (result1);
const call2Promise = rp ( '
const call3Promise = rp ( '
retour Promise.all ( );
}). Ensuite (arr = > {
// Après deux promesse interprétera les deux extrémités
console.log (arr );
console.log (arr );
})
Nous commençons à créer la première requête HTTP, et ajouté un temps d'exécution de rappel d'achèvement (lignes 1-3). Dans la fonction de rappel, nous créons deux promesses supplémentaires (8-9 lignes) pour les demandes ultérieures HTTP. Les deux promettent en même temps pour effectuer, et nous devons être en mesure d'ajouter une fonction de rappel après avoir terminé l'exécution. Nous avons donc besoin Promise.all les combiner en une seule promesse (ligne 11), après avoir mis fin à cette promesse est terminée. Ceci est une promesse de retourner l'objet de rappel, donc nous avons besoin d'ajouter une fonction de rappel, puis imprimer le résultat (lignes 12-16).
Le schéma suivant illustre le processus de calcul:
Promise combinaison processus de calcul. Nous utiliserons deux Promise.all promesse parallèle combinée à une promesse.
Pour cet exemple simple, nous avons passé les deux dernières méthode, puis le rappel, et a dû utiliser Promise.all pour faire deux promesse parallèle simultanément. Si nous devons effectuer une opération plus asynchrone, ou ajouter la gestion des erreurs ce qui se passera? Cette dernière méthode peut facilement conduire à un tas d'ordures puis, Promise.all et callbacks.
méthode async
Async est un moyen rapide de définir la fonction de la promesse de retour cible.
Par exemple, les deux définitions suivantes sont équivalentes:
la fonction f () {
retourner Promise.resolve ( 'TEST');
}
// asyncF et f sont équivalentes
async fonction asyncF () {
retour 'TEST';
}
De même, la méthode async jette un retour d'exception est équivalente à la méthode de promesse de rejet:
la fonction f () {
retourner Promise.reject ( 'Erreur');
}
// asyncF et f sont équivalentes
async fonction asyncF () {
jeter « Erreur »;
}
Attendent
Nous avons créé la promesse, mais ne peut pas attendre pour effectuer une synchronisation complète. Nous ne pouvons passer une fonction de rappel alors. Nous ne sommes pas autorisés à attendre la promesse d'encourager le développement du code non-bloquant. Dans le cas contraire, les développeurs ne pouvaient pas toujours effectuer des opérations de blocage, car il est plus simple que d'utiliser la promesse et callbacks.
Toutefois, afin de synchroniser la promesse d'exécution, nous devons les amener à attendre la fin de l'autre. En d'autres termes, si une opération est asynchrone (à savoir, encapsulé dans la promesse), il devrait être en mesure d'attendre une autre opération asynchrone exécutée. Mais l'interpréteur JavaScript pour savoir comment l'opération est en cours d'exécution dans une promesse en elle?
La réponse se trouve dans le mot-clé. Async Chaque méthode async retourne un objet de promesse. Par conséquent, interpréteur JavaScript pour comprendre le fonctionnement de toutes les méthodes async sont encapsulés dans la promesse de l'exécution asynchrone. Par conséquent interprète pour leur permettre d'attendre que d'autres promesses d'exécution.
Attendre la mise en mots-clés suivants. Il ne peut être utilisé dans la méthode async, afin que nous puissions attendre la promesse de synchronisation exécutée. Si vous utilisez la promesse en dehors de la fonction async, alors nous avons encore besoin d'utiliser une fonction de rappel:
async fonction f () {
// réponse est la valeur de la mise en uvre réussie de la promesse
réponse const = await rp ( '
console.log (réponse);
}
// méthode async ne peut pas être utilisé sévissent à l'extérieur
// fonction de rappel est nécessaire, alors ......
f (). puis (() = > console.log ( 'fini'));
Maintenant, nous regardons comment résoudre le problème sur l'un des:
// La solution est encapsulée dans la fonction async
solution de fonction asynchrone () {
// attente pour la première requête HTTP et imprimer les résultats
console.log (await rp ( '
// Créer deux requêtes HTTP, allant de leur exécution complète - en même temps leur permettent d'effectuer
const call2Promise = rp ( ' // N'attend pas!
const call3Promise = rp ( ' // N'attend pas!
// Une fois que vous avez créé - en attente pour eux d'effectuer complète
const response2 = await call2Promise;
const réponse3 = await call3Promise;
console.log (response2);
console.log (réponse3);
}
// appel de cette fonction async
solution (). puis (() = > console.log ( 'fini'));
Dans le code ci-dessus, la solution que nous encapsulé dans la fonction async. Cela nous permet d'utiliser le mot-clé await directement à l'intérieur de la promesse, alors il n'y a pas besoin d'utiliser une fonction de rappel. Enfin, appelez async cette fonction, il crée simplement un objet de la promesse, et cette promesse encapsule les appels vers d'autres promesses de la logique.
Bien sûr, dans le premier exemple (sans async / Attendent), la promesse deux sont déclenchées simultanément. Ce code est le même (lignes 7-8). Notez que jusqu'à la ligne 11-12, nous utilisons await, le programme a été bloqué pour compléter les deux promesse d'exécuter. Ensuite, nous pouvons conclure que les deux cas sont la mise en uvre réussie de la promesse (et l'utilisation Promise.all (...) .alors (...) similaire).
Continuez le processus de calcul derrière cela est à peu près égale à une donnée. Mais le code plus lisible et plus facile à comprendre.
En fait, async / vous attendent au bas de la promesse, puis convertie en une fonction de rappel. En d'autres termes, il est la promesse d'utiliser le sucre de syntaxe. Chaque fois que nous utilisons await, l'interprète crée un objet promesse et puis utiliser le reste de la fonction async en place alors la fonction de rappel.
Regardons l'exemple suivant:
async fonction f () {
console.log ( 'A partir F');
résultat const = await rp ( '
console.log (résultat);
}
On nous donne ci-dessous fonction f processus de calcul sous-jacent. Puisque f est async, il sera exécuté en même temps que l'appelant dit:
Attendre le processus de calcul.
La fonction f exécute et crée un objet promesse. A ce moment, les pièces de fonction restantes sont encapsulées dans une fonction de rappel, et exécutés après la promesse.
Gestion des erreurs
La plupart de l'exemple précédent, nous supposons que cette promesse exécutée avec succès. Par conséquent attendre la valeur de retour sur la promesse. Si nous promettons await a échoué, sauf la fonction async se produit. Nous pouvons utiliser un try / catch standard pour gérer cette situation:
async fonction f () {
try {
const promiseResult = await Promise.reject ( 'Erreur');
} Catch (e) {
console.log (e);
}
}
fonction Async ne gère pas l'exception, aucune anomalie de la matière sont causées par le refus de la promesse ou tout autre bug, et il retournera une promesse de refus:
async fonction f () {
// Renvoie une exception
const promiseResult = await Promise.reject ( 'Erreur');
}
// Affichera « Erreur »
f ().
puis (() = > console.log ( 'succès')).
catch (err = > console.log (err))
async fonction g () {
jeter « Erreur »;
}
// Affichera « Erreur »
g ().
puis (() = > console.log ( 'succès')).
catch (err = > console.log (err))
discuter
Async / promesse await est de rendre la langue de la structure plus parfaite. Il nous permet d'utiliser moins de code en utilisant la promesse. Cependant, async / Attendent n'a pas remplacé la promesse ordinaire. Par exemple, si l'appel de fonction ou de synchronisation dans une fonction ordinaire au niveau mondial, nous avons aucun moyen que d'utiliser await dépend de la promesse générale :
async fonction FASYNC () {
// valeur de retour réelle est Promise.resolve (5)
retour 5;
}
// ne peut pas appeler "await FASYNC ()". Besoin d'utiliser alors / catch
FASYNC (). puis (r = > console.log ( `résultat est $ {r}`));
Je généralement la logique la plus asynchrone encapsulés dans une ou plusieurs fonctions async, puis appeler le code non-asynchrone. Il me fait écrire aussi peu que possible try / catch rappel.
la structure Async / await est de promettre d'utiliser le sucre de syntaxe plus concise de. Chaque structure async / Attendent peut être écrit comme promesse ordinaire. En fin de compte, il est un style de codage et des questions concises.
Remarques sur les informations différenciées concurrence et parallélisme, vous pouvez vérifier la discussion Rob Pike sur cette question ou mon article. Concurrency fait référence au processus indépendant (processus dans le sens habituel) de travailler ensemble, et parallèle moyenne, vraiment gérer plusieurs tâches simultanément. En même temps se rapportant à la conception d'applications et l'architecture, et parallèlement à l'exécution réelle.
Nous prenons une application multi-thread par exemple. Applications séparées dans son modèle de fil clair concurrency. Ces fils mappés sur les noyaux disponibles ou définit son parallélisme de niveau. système concurrent peut fonctionner efficacement sur un seul processeur, auquel cas, il n'est pas parallèle.
VS simultané en parallèle
En ce sens, nous nous engageons pour que nous puissions être décomposées en modules de programme simultanés qui peuvent ou peuvent ne pas être exécutées en parallèle. Aucune Javascript effectuée réelle en parallèle en fonction de la mise en uvre particulière. Par exemple, le nud JS est mono-thread, il n'y aurait aucune promesse si le traitement parallèle est intensive informatiquement (CPU liée). Cependant, si vous utilisez quelque chose comme Nashorn le code Java en code binaire, il peut être calculé théoriquement possible promesse intensive mis en correspondance avec différents curs de processeurs pour atteindre parallélisation. Donc, je pense, la promesse (générale ou avec le async / Attendent a) la composition du bloc concurrent applications JavaScript.