Pendant le processus d'écriture de Node.js, les opérations d'IO continues peuvent conduire à "Pyramid Nightmare". La nidification multiple des fonctions de rappel rend le code difficile à maintenir. La promesse de CommonJS est utilisée pour encapsuler les fonctions asynchrones et utiliser une API de chaîne unifiée pour se débarrasser du cauchemar de plusieurs rappels.
Le modèle IO non bloquant fourni par Node.js nous permet d'utiliser des fonctions de rappel pour gérer les opérations IO, mais lorsque des opérations d'IO continues sont nécessaires, vos fonctions de rappel seront imbriquées plusieurs fois, le code n'est pas beau, et il n'est pas facile de maintenir, et il peut y avoir de nombreux codes répétés pour la gestion des erreurs, qui est le "pyramide de Doom".
La copie de code est la suivante:
étape 1 (fonction (valeur1) {
Step2 (valeur1, fonction (valeur2) {
étape3 (valeur2, fonction (valeur3) {
Step4 (valeur3, fonction (valeur4) {
// faire quelque chose avec la valeur4
});
});
});
});
C'est en fait le problème du flux de contrôle dans Node.js. Il existe de nombreuses solutions à ce problème, comme l'utilisation de l'async, de l'événementProxy, etc. Cependant, le sujet de cet article est d'utiliser la promesse dans la spécification CommonJS pour résoudre ce problème.
Qu'est-ce que la promesse?
Il existe de nombreux types de spécifications de promesses pour les CommonJS. Nous discutons généralement de la spécification Promise / A +, qui définit le comportement de base de la promesse.
Une promesse est un objet qui représente généralement une opération asynchrone qui pourrait être achevée à l'avenir. Cette opération peut réussir ou échouer, donc un objet de promesse a généralement 3 états: en attente, rempli et rejeté. Il représente respectivement l'achèvement et la défaillance de l'opération inachevés et réussis. Une fois que l'état de l'objet de promesse passe de l'attention à la réalisation ou au rejet, son état ne peut plus être modifié.
Un objet Promise a généralement une méthode alors, qui nous permet de faire fonctionner la valeur renvoyée après un éventuel succès à l'avenir ou la raison de l'échec. Cette méthode ressemble alors à ceci:
promesse.
Il est évident que la méthode puis accepte deux paramètres, qui sont généralement deux fonctions, l'une est utilisée pour traiter le résultat après le succès de l'opération, et l'autre est utilisé pour traiter la cause de la défaillance de l'opération. Les premiers paramètres de ces deux fonctions sont le résultat après le succès et la cause de l'échec. Si la méthode alors n'est pas une fonction, ce paramètre sera ignoré.
La valeur de retour de la méthode alors est un objet de promesse, qui nous permet d'appeler ensuite l'appel pour atteindre l'effet du contrôle du processus. Il existe de nombreux détails ici, tels que le transfert de valeur ou la gestion des erreurs. La spécification de promesse est définie comme ceci:
La valeur de retour de la fonction onfullable ou sur le projection n'est pas un objet de promesse, alors la valeur sera utilisée comme premier paramètre de sur la méthode suivante. Si la valeur de retour est un objet de promesse, comment la valeur de retour de la méthode alors peut-elle être l'objet Promise
Si une exception est lancée dans la fonction onfulllée ou sur le projection, l'état de l'objet prometteur de la méthode alors renvoyé est converti en rejet. Si l'objet Promise appelle alors, l'objet d'erreur sera utilisé comme premier paramètre de la fonction onRERFED.
Si l'état de promesse se remplit et que la fonction surfacée n'est pas fournie dans la méthode alors, l'état d'objet Promise renvoyé par la méthode alors se réalise et le résultat réussi est le résultat de la promesse précédente, il en va de même pour rejeter.
Pour ajouter, à la fois à la fois définis et sur les projections sont exécutés de manière asynchrone.
Mise en œuvre de spécifications: Q
Ce qui précède concerne la spécification de la promesse, et ce dont nous avons besoin, c'est de sa mise en œuvre. Q est une bibliothèque qui a de meilleures spécifications de mise en œuvre pour Promise / A +.
Tout d'abord, nous devons créer un objet de promesse. Les spécifications pour la création de Promise Object sont en promesse / b. Je n'expliquerai pas en détail ici, ajoutez simplement le code.
La copie de code est la suivante:
fonction (drapeau) {
var defer = q.defer ();
fs.readfile ("a.txt", fonction (err, data) {
if (err) defer.reject (err);
else defer.resolve (data);
});
retour de retour.promes;
}
La plupart des implémentations de promesses sont similaires dans la création de promesses. En créant un objet de différence avec l'attribut Promise, si la valeur est obtenue avec succès, Defer.Resolve (Value) est appelé, s'il échoue, Defer.Reject (Raison) est appelé, et enfin renvoyez l'attribut Promise de Defer. Ce processus peut être compris comme l'appel de report. Resolve transforme l'état de la promesse en réalisation, et l'appel de report.Reject transforme l'état de la promesse en rejet.
Lorsqu'ils sont confrontés à une série de méthodes asynchrones continues, comment pouvez-vous écrire un beau code en utilisant la promesse? Jetez un œil à l'exemple suivant.
La copie de code est la suivante:
promesse0.Then (fonction (résultat) {
// Dosomething
Résultat de retour;
}). puis (fonction (résultat) {
// Dosomething
Retour Promise1;
}). puis (fonction (résultat) {
// Dosomething
}). Catch (fonction (ex) {
console.log (ex);
}). Enfin (fonction () {
console.log ("final");
});
Dans le code ci-dessus, la méthode alors accepte uniquement onfullable, et la méthode de capture est en fait alors (null, onrejected). De cette façon, tant qu'une série de méthodes asynchrones renvoie toujours les valeurs avec succès, le code va vers le bas dans un style de cascade. Si l'une des méthodes asynchrones échoue ou si une exception se produit, alors selon la spécification CommonJS Promise, la fonction dans la capture sera exécutée. Q fournit également une méthode finalement, qui est facile à comprendre littéralement, c'est-à-dire qu'elle résout ou rejette, la fonction dans finalement sera exécutée.
Il a l'air bien, le code est plus entretenu et beau, alors que se passe-t-il si vous voulez de la concurrence?
La copie de code est la suivante:
Q.all ([Promise0, Promise1, Promise2]). Scand (fonction (Val0, Val1, Val2) {
console.log (arguments);
}). puis (fonction () {
console.log ("fait");
}). Catch (fonction (err) {
console.log (err);
});
Q fournit également une API pour la concurrence, appeler toutes les méthodes et passer un tableau de promesses peut continuer à utiliser le style de chaîne de alors. Il y a aussi de bonnes choses comme q.nfbind, etc. qui peuvent convertir l'API native de Node.js en promesse d'unifier le format de code. D'autres API ne seront pas décrites en détail ici.
en conclusion
Cet article introduit principalement l'utilisation de la promesse pour résoudre le problème de flux de contrôle Node.js, mais la promesse peut également être appliquée à l'avant. EmCascript6 a fourni un support d'API natif. Il convient de souligner que la promesse n'est pas la seule solution, l'async est également un bon choix et fournit une API de contrôle de concurrence plus amicale, mais je pense que la promesse a plus d'avantages lors de l'encapsulation des fonctions avec des méthodes asynchrones.
D'accord, c'est tout pour cet article, j'espère que cela sera utile à tout le monde.