web-dev-qa-db-de.com

Versprechen in Node.js verstehen

Soweit ich verstanden habe, gibt es drei Möglichkeiten, asynchronen Code aufzurufen:

  1. Ereignisse, z.B. request.on("event", callback);
  2. Rückrufe, z.B. fs.open(path, flags, mode, callback);
  3. Versprechen

Ich habe die Node-Promise-Bibliothek gefunden, aber ich verstehe sie nicht.

Könnte jemand erklären, worum es bei Versprechungen geht und warum ich sie verwenden sollte?

Warum wurde es auch aus Node.js entfernt?

146
ajsie

Versprechungen in node.js versprachen, etwas Arbeit zu leisten, und hatten dann separate Rückrufe, die für Erfolg und Misserfolg sowie für die Behandlung von Zeitüberschreitungen ausgeführt wurden. Eine andere Möglichkeit, Versprechungen in node.js zu betrachten, bestand darin, dass es sich um Emittenten handelte, die nur zwei Ereignisse auslösen konnten: Erfolg und Fehler.

Das Coole an Versprechungen ist, dass Sie sie zu Abhängigkeitsketten zusammenfassen können (machen Sie Versprechen C nur, wenn Versprechen A und Versprechen B abgeschlossen sind).

Durch das Entfernen aus dem core node.js wurde die Möglichkeit geschaffen, Module mit unterschiedlichen Implementierungen von Versprechungen aufzubauen, die auf dem core sitzen können. Einige davon sind Knotenversprechen und Futures .

90
Paul Robinson

Da diese Frage noch viele Ansichten hat (wie meine), wollte ich darauf hinweisen, dass:

  1. Node-Promise sieht für mich ziemlich tot aus (das letzte Commit war vor ungefähr 1 Jahr) und enthält fast keine Tests.
  2. Das Futures Modul sieht für mich sehr aufgebläht aus und ist schlecht dokumentiert (und ich denke, dass die Namenskonventionen einfach schlecht sind)
  3. Der beste Weg scheint das q-Framework zu sein, das sowohl aktiv als auch gut dokumentiert ist.
98
enyo

Ein Versprechen ist ein "Ding", das sozusagen das "mögliche" Ergebnis einer Operation darstellt. Der hier zu beachtende Punkt ist, dass es die Details von abstrahiert, wenn etwas passiert, und es Ihnen ermöglicht, sich auf das zu konzentrieren, was passieren soll danach passiert etwas. Dies führt zu sauberem, wartbarem Code. Anstatt einen Rückruf innerhalb eines Rückrufs innerhalb eines Rückrufs zu haben, sieht Ihr Code folgendermaßen aus:

 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
 });

Die Spezifikation der Versprechen besagt, dass ein Versprechen ist

then

die Methode sollte eine neue Zusage zurückgeben, die erfüllt ist, wenn der angegebene successHandler- oder failureHandler-Rückruf beendet ist. Dies bedeutet, dass Sie Versprechen verketten können, wenn Sie über eine Reihe von asynchronen Aufgaben verfügen, die ausgeführt werden müssen, und sicherstellen können, dass die Reihenfolge der Vorgänge so gewährleistet ist, als ob Sie Rückrufe verwendet hätten. Anstatt einen Rückruf innerhalb eines Rückrufs innerhalb eines Rückrufs zu übergeben, sieht der Code mit verketteten Versprechungen folgendermaßen aus:

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

Um mehr über Versprechen zu erfahren und zu erfahren, warum sie super cool sind, lesen Sie Domenics Blog: http://domenic.me/2012/10/14/youre-missing-the-point-of-promises/

19
Hrishi

Dieses neues Tutorial zu Versprechen des Autors von PouchDB ist wahrscheinlich das Beste, das ich je gesehen habe. Es behandelt klugerweise die klassischen Anfängerfehler, die Ihnen korrekte Verwendungsmuster und sogar ein paar Antimuster zeigen, die immer noch häufig verwendet werden - sogar in anderen Tutorials!

Genießen!

PS: Ich habe einige andere Teile dieser Frage nicht beantwortet, da sie von anderen gut behandelt wurden.

12
Tony O'Hagan

Mike Taulty hat eine Reihe von Videos , die jeweils weniger als zehn Minuten lang sind und beschreiben, wie die WinJS Promise-Bibliothek funktioniert.

Diese Videos sind sehr informativ und Mike schafft es, die Leistungsfähigkeit der Promise-API anhand einiger gut ausgewählter Codebeispiele zu demonstrieren.

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
     });

Die Behandlung von Ausnahmen ist besonders gut.

Trotz der WinJs-Referenzen handelt es sich um eine Videoserie von allgemeinem Interesse, da die Promise-API in ihren vielen Implementierungen weitgehend ähnlich ist.

RSVP ist eine einfache Promise-Implementierung, die die Promise/A + -Testsuite besteht. Die API gefällt mir sehr gut, da sie im Stil der WinJS-Oberfläche ähnelt.

Update April 2014

Übrigens ist die WinJS-Bibliothek ist jetzt Open Source .

7
Noel Abrahams

Ein weiterer Vorteil von Versprechungen ist, dass Fehlerbehandlung und das Auslösen und Abfangen von Ausnahmen viel besser sind als der Versuch, dies mit Rückrufen zu behandeln.

Die Bluebird Bibliothek implementiert Versprechungen und gibt Ihnen großartige lange Stack-Traces, ist sehr schnell und warnt vor nicht erfassten Fehlern. Laut http://bluebirdjs.com/docs/benchmarks.html ist es auch schneller und belegt weniger Speicher als die anderen vielversprechenden Bibliotheken

5
llambda

Was genau ist ein Versprechen?

Ein Versprechen ist einfach ein Objekt, das das Ergebnis einer asynchronen Operation darstellt. Ein Versprechen kann in einem der folgenden 3 Zustände sein:

pending :: Dies ist der Ausgangszustand, dh das Versprechen wird weder erfüllt noch abgelehnt.

erfüllt :: Dies bedeutet, dass das Versprechen erfüllt wurde, dh, der durch das Versprechen dargestellte Wert kann verwendet werden.

abgelehnt :: Dies bedeutet, dass die Operationen fehlgeschlagen sind und daher das Versprechen nicht erfüllen können. Abgesehen von den Staaten gibt es drei wichtige Einheiten, die mit Versprechen verbunden sind, die wir wirklich verstehen müssen

  1. executor function :: executor function definiert die asynchrone Operation, die ausgeführt werden muss und deren Ergebnis durch das Versprechen dargestellt wird. Die Ausführung wird gestartet, sobald das Versprechungsobjekt initialisiert wurde.

  2. resolve :: resolve ist ein Parameter, der an die Executor-Funktion übergeben wird. Wenn der Executor erfolgreich ausgeführt wird, wird diese Auflösung als Übergabe des Ergebnisses bezeichnet.

  3. reject :: reject ist ein weiterer Parameter, der an die Executor-Funktion übergeben wird und verwendet wird, wenn die Executor-Funktion fehlschlägt. Der Fehlergrund kann an den Ausschuss weitergegeben werden.

Wenn wir also ein Versprechungsobjekt erstellen, müssen wir Executor, Resolve und Reject bereitstellen.

Referenz :: Versprechen

4
Rishabh.IO

Ich habe in letzter Zeit auch in node.js nach Versprechungen gesucht. Bisher scheint das when.js aufgrund seiner Geschwindigkeit und Ressourcenauslastung der richtige Weg zu sein, aber die Dokumentation zu q.js hat mir ein viel besseres Verständnis vermittelt. Verwenden Sie also when.js, aber die q.js-Dokumentation, um das Thema zu verstehen.

Aus der q.js Readme auf Github:

Wenn eine Funktion keinen Wert zurückgeben oder eine Ausnahme auslösen kann, ohne sie zu blockieren, kann sie stattdessen ein Versprechen zurückgeben. Ein Versprechen ist ein Objekt, das den Rückgabewert oder die ausgelöste Ausnahme darstellt, die die Funktion eventuell bereitstellt. Ein Versprechen kann auch als Proxy für ein entferntes Objekt verwendet werden, um die Latenz zu überwinden.

0
Andrew Roberts