Comprendre les promesses dans Node.js

147

D'après ce que j'ai compris, il existe trois façons d'appeler du code asynchrone:

  1. Événements, par exemple request.on("event", callback);
  2. Rappels, par exemple fs.open(path, flags, mode, callback);
  3. Promesses

J'ai trouvé la bibliothèque node-promise mais je ne la comprends pas.

Quelqu'un pourrait-il expliquer en quoi consistent les promesses et pourquoi je devrais les utiliser?

Aussi, pourquoi a-t-il été supprimé de Node.js?

Ajsie
la source
Cet article l' explique plutôt bien. Quand il s'agit d'une implémentation utilisable dans node.js, jetez un œil à Futures
Sean Kinsey
Voici une excellente série que j'ai utilisée pour créer ma propre classe de promesse: Faisons un cadre: Promesses Voici une vidéo sur jQuery Deferred: blog.bigbinary.com/2011/09/03/jquery-deferred.html
Tom Winter

Réponses:

91

Les promesses dans node.js promettaient de faire un peu de travail et avaient ensuite des rappels séparés qui seraient exécutés en cas de succès et d'échec ainsi que de gestion des délais d'expiration. Une autre façon de penser aux promesses dans node.js était qu'ils étaient des émetteurs qui ne pouvaient émettre que deux événements: le succès et l'erreur.

La chose intéressante à propos des promesses est que vous pouvez les combiner dans des chaînes de dépendances (ne faites la promesse C que lorsque la promesse A et la promesse B sont terminées).

En les supprimant du noyau node.js, cela a créé la possibilité de construire des modules avec différentes implémentations de promesses qui peuvent se trouver au-dessus du noyau. Certains d'entre eux sont la promesse des nœuds et les futurs .

Paul Robinson
la source
10
@weng Non, ce n'est pas le cas.
Ivo Wetzel
98

Étant donné que cette question a encore de nombreux points de vue (comme le mien), je tenais à souligner que:

  1. node-promise me semble plutôt mort (le dernier commit date d'il y a environ 1 an) et ne contient presque aucun test.
  2. Le module Futures me semble très gonflé et est mal documenté (et je pense que les conventions de nommage sont tout simplement mauvaises)
  3. La meilleure solution semble être le cadre q , qui est à la fois actif et bien documenté.
enyo
la source
9
Vérifiez aussi ce github.com/medikoo/deferred , Q est l'un des premiers et c'est certainement l'inspiration pour de nombreuses implémentations qui sont apparues par la suite, mais malheureusement c'est très lent et trop "théorique" dans certaines parties, il ne joue pas bien avec certaines scénarios du monde réel
Mariusz Nowak
Je regarderais cette vidéo sur les promesses de l'un des créateurs de RSVP.js youtube.com
...
23
Mise à jour 2014 - bluebird est de loin le plus rapide et celui avec les meilleures capacités de débogage aujourd'hui.
Benjamin Gruenbaum
19

Une promesse est une «chose» qui représente les résultats «éventuels» d'une opération pour ainsi dire. Le point à noter ici est que cela fait abstraction des détails du moment où quelque chose se produit et vous permet de vous concentrer sur ce qui devrait se passer après que quelque chose se passe. Cela se traduira par un code propre et maintenable où au lieu d'avoir un rappel dans un rappel à l'intérieur d'un rappel, votre code ressemblera un peu à:

 var request = new Promise(function(resolve, reject) {
   //do an ajax call here. or a database request or whatever.
   //depending on its results, either call resolve(value) or reject(error)
   //where value is the thing which the operation's successful execution returns and
   //error is the thing which the operation's failure returns.
 });

 request.then(function successHandler(result) {
   //do something with the result
 }, function failureHandler(error) {
  //handle
 });

La spécification des promesses indique qu'une promesse

then

doit retourner une nouvelle promesse qui est remplie lorsque le rappel successHandler ou failureHandler donné est terminé. Cela signifie que vous pouvez enchaîner les promesses lorsque vous avez un ensemble de tâches asynchrones à effectuer et être assuré que le séquencement des opérations est garanti comme si vous aviez utilisé des rappels. Ainsi, au lieu de passer un callback dans un callback dans un callback, le code avec des promesses enchaînées ressemble à:

var doStuff = firstAsyncFunction(url) {
                return new Promise(function(resolve, reject) {
                       $.ajax({
                        url: url,
                        success: function(data) {
                            resolve(data);
                        },
                        error: function(err) {
                             reject(err); 
                        } 
                  });
               };
doStuff
  .then(secondAsyncFunction) //returns a promise
  .then(thirdAsyncFunction); //returns a promise

Pour en savoir plus sur les promesses et pourquoi elles sont super cool, consultez le blog de Domenic: http://domenic.me/2012/10/14/youre-missing-the-point-of-promises/

Hrishi
la source
12

Ce nouveau tutoriel sur les promesses de l'auteur de PouchDB est probablement le meilleur que j'aie jamais vu. Il couvre sagement les erreurs classiques des recrues en vous montrant des modèles d'utilisation corrects et même quelques anti-modèles qui sont encore couramment utilisés - même dans d'autres tutoriels !!

Prendre plaisir!

PS Je n'ai pas répondu à certaines autres parties de cette question car elles ont été bien couvertes par d'autres.

Tony O'Hagan
la source
Ma seule excuse pour cela est de vous obliger à lire l'humour à la fin de l'erreur avancée n ° 4.
Tony O'Hagan
En fait, le code du didacticiel qu'ils prétendent être un anti-modèle a besoin de l'imbrication de la boucle et de la condition, et ne peut pas être aussi facilement aplati qu'ils le suggèrent.
Bergi
L'erreur avancée n ° 4 peut également être résolue en utilisant un nombre beaucoup plus grand d'approches différentes, voir Comment accéder aux résultats de promesse précédents dans une chaîne .then ()? (le modèle de fermeture qu'ils suggèrent ne semble pas très populaire).
Bergi
Je pense que cette réponse de lien seulement aurait dû être un commentaire. Veuillez mettre au moins les principaux points de cet article dans votre réponse ici.
Bergi
7

Mike Taulty a une série de vidéos , chacune de moins de dix minutes, décrivant le fonctionnement de la bibliothèque WinJS Promise.

Ces vidéos sont assez informatives et Mike parvient à montrer la puissance de l'API Promise avec quelques exemples de code bien choisis.

var twitterUrl = "http://search.twitter.com/search.json?q=windows";
var promise = WinJS.xhr({ url: twitterUrl });

 promise = promise.then(
     function (xhr) {
     },
     function (xhr) {
         // handle error
     });

Le traitement des exceptions est particulièrement bon.

Malgré les références WinJs, il s'agit d'une série de vidéos d'intérêt général, car l'API Promise est globalement similaire dans ses nombreuses implémentations.

RSVP est une implémentation légère de Promise qui passe la suite de tests Promise / A +. J'aime assez l'API, car son style est similaire à celui de l'interface WinJS.

Mise à jour avril-2014

Incidemment, la bibliothèque WinJS est désormais open source .

Noel Abrahams
la source
1
+1. C'est le premier exemple que j'ai vu qui me semble logique et qui est intuitif à utiliser. D'une manière ou d'une autre, mon cerveau ne peut pas analyser tous les prédéfinis deferredset resolveet deferred.promise.thenet promiseActionsdans la documentation populaire de la bibliothèque Q. Avez-vous une chance de savoir quelque chose d'aussi simple pour Node.js ?
Redsandro
1
@noel merci d'avoir partagé le lien ci-dessus, c'est une excellente série d'introduction pour les promesses, et je conviens que les spécificités de WinJS ne sont pas pertinentes car l'approche / le sujet global est universel.
arcseldon
Bel exemple. J'ai aussi réparé votre premier lien qui était mort
stonedauwg
5

Un autre avantage des promesses est que la gestion des erreurs et la levée et la capture d'exceptions sont bien meilleures que d'essayer de gérer cela avec des rappels.

La bibliothèque bluebird met en œuvre des promesses et vous donne d'excellentes traces de longue pile, est très rapide et avertit des erreurs non interceptées. Il est également plus rapide et utilise moins de mémoire que les autres bibliothèques de promesse, selon http://bluebirdjs.com/docs/benchmarks.html

Llambda
la source
4

Qu'est-ce qu'une promesse exactement?

Une promesse est simplement un objet qui représente le résultat d'une opération asynchrone. Une promesse peut être dans l'un des 3 états suivants:

en attente :: Ceci est l'état initial, signifie que la promesse n'est ni tenue ni rejetée.

rempli : Cela signifie que la promesse a été remplie, signifie que la valeur représentée par la promesse est prête à être utilisée.

rejeté :: Cela signifie que les opérations ont échoué et ne peuvent donc pas tenir la promesse. Outre les États, il y a trois entités importantes associées aux promesses que nous devons vraiment comprendre

  1. executor function :: executor function définit l'opération asynchrone qui doit être effectuée et dont le résultat est représenté par la promesse. Il démarre l'exécution dès que l'objet de promesse est initialisé.

  2. résoudre :: résoudre est un paramètre passé à la fonction exécuteur, et si l'exécuteur s'exécute avec succès, cette résolution est appelée en passant le résultat.

  3. Rejeter :: Rejeter est un autre paramètre passé à la fonction exécuteur, et il est utilisé lorsque la fonction exécuteur échoue. La raison de l'échec peut être transmise au rejet.

Ainsi, chaque fois que nous créons un objet de promesse, nous devons fournir Executor, Resolve et Reject.

Référence: Promises

Rishabh.IO
la source
0

J'ai également étudié les promesses dans node.js récemment. À ce jour, le when.js semble être la voie à suivre en raison de sa vitesse et de son utilisation des ressources, mais la documentation sur q.js m'a permis de mieux comprendre. Utilisez donc when.js mais la documentation q.js pour comprendre le sujet.

Depuis le readme de q.js sur github:

Si une fonction ne peut pas renvoyer une valeur ou lever une exception sans blocage, elle peut renvoyer une promesse à la place. Une promesse est un objet qui représente la valeur de retour ou l'exception levée que la fonction peut éventuellement fournir. Une promesse peut également être utilisée comme proxy pour un objet distant pour surmonter la latence.

Andrew Roberts
la source
0

L'objet Promise représente l'achèvement ou l'échec d'une opération asynchrone.

Donc, pour mettre en œuvre une promesse, vous avez besoin de deux parties: -

1. Création de la promesse:

Le constructeur de promesse accepte une fonction appelée exécuteur qui a 2 paramètres de résolution et de rejet.

function example(){
   return new Promise (function(resolve , reject){   //return promise object
      if(success){
         resolve('success');  //onFullfiled
      }else{
         reject('error');     //onRejected
      }
   })
}

2. Promesse de traitement:

L'objet Promise a 3 méthodes pour gérer les objets Promise: -

1.Promise.prototype.catch (onRejected)

2.Promise.prototype.then (onFullfiled)

3.Promise.prototype.finalement (onFullfiled, onRejected)

example.then((data) =>{
  //handles resolved data
  console.log(data); //prints success     
}).catch((err) => {
  //handles rejected error 
  console.log(err);  //prints error
})
Pavneet Kaur
la source