Versprechen in Node.js verstehen


147

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

  1. Ereignisse, z request.on("event", callback);
  2. Rückrufe, z 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?


Dieser Artikel erklärt es ziemlich gut. Wenn es um eine Implementierung geht, die in node.js verwendet werden kann, werfen Sie einen Blick auf Futures
Sean Kinsey

Hier ist eine großartige Serie, mit der ich meine eigene Versprechen-Klasse erstellt habe: Lassen Sie uns ein Framework erstellen : Versprechen Hier ist ein Video über jQuery Deferred: blog.bigbinary.com/2011/09/03/jquery-deferred.html
Tom Winter

Antworten:


91

Versprechen in node.js versprachen, einige Arbeiten auszuführen, 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, sich Versprechen in node.js vorzustellen, bestand darin, dass es sich um Emitter handelte, die nur zwei Ereignisse ausgeben konnten: Erfolg und Fehler.

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

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


10
@weng Nein, ist es nicht.
Ivo Wetzel

98

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

  1. Node-Promise sieht für mich ziemlich tot aus (letztes 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.

9
Überprüfen Sie auch diese github.com/medikoo/deferred , Q ist eine der ersten und es ist definitiv Inspiration für viele Implementierungen, die danach erschienen, aber leider ist es in einigen Teilen sehr langsam und zu "theoretisch", es spielt mit einigen nicht gut reale Szenarien
Mariusz Nowak

Ich würde dieses Video auf Versprechen von einem der Schöpfer von RSVP.js youtube.com/…
runspired

23
Update 2014 - Bluebird ist bei weitem der schnellste und derjenige mit den besten Debugging-Fähigkeiten heute.
Benjamin Gruenbaum

19

Ein Versprechen ist ein "Ding", das sozusagen die "möglichen" Ergebnisse einer Operation darstellt. Der Punkt hier zu beachten ist , dass es abstrahiert die Details , wenn etwas passiert , und ermöglicht es Ihnen , sich darauf zu konzentrieren , was passieren soll , nachdem das etwas passiert. Dies führt zu sauberem, wartbarem Code, bei dem anstelle eines Rückrufs innerhalb eines Rückrufs innerhalb eines Rückrufs Ihr Code ungefähr so ​​aussieht:

 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 ein neues Versprechen zurückgeben, das erfüllt wird, wenn der angegebene SuccessHandler- oder FailureHandler-Rückruf beendet ist. Dies bedeutet, dass Sie Versprechen verketten können, wenn Sie eine Reihe von asynchronen Aufgaben haben, die ausgeführt werden müssen, und sicher sein können, dass die Reihenfolge der Vorgänge so gewährleistet ist, als hätten Sie Rückrufe verwendet. Anstatt einen Rückruf innerhalb eines Rückrufs innerhalb eines Rückrufs weiterzuleiten, 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 warum sie super cool sind, lesen Sie Domenics Blog: http://domenic.me/2012/10/14/youre-missing-the-point-of-promises/


12

Dieses neue Tutorial zu Promises vom Autor von PouchDB ist wahrscheinlich das beste, das ich je gesehen habe. Es deckt mit Bedacht die klassischen Anfängerfehler ab, die Ihnen korrekte Verwendungsmuster und sogar einige Anti-Muster 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.


Ich entschuldige mich nur dafür, dass Sie gezwungen sind, am Ende von Advanced Fehler Nr. 4 Humor zu lesen.
Tony O'Hagan

Tatsächlich benötigt der Code im Tutorial, von dem behauptet wird, er sei ein Antimuster, die Verschachtelung für die Schleife und die Bedingung und kann nicht so leicht abgeflacht werden, wie sie vorschlagen.
Bergi

Der erweiterte Fehler Nr. 4 kann auch mit einer weitaus größeren Anzahl unterschiedlicher Ansätze behoben werden. Siehe Wie greife ich in einer .then () -Kette auf frühere Versprechungsergebnisse zu? (Das von ihnen vorgeschlagene Verschlussmuster scheint nicht sehr beliebt zu sein).
Bergi

Ich denke, diese Nur-Link-Antwort hätte besser ein Kommentar sein sollen. Bitte geben Sie in Ihrer Antwort hier mindestens die wichtigsten Punkte dieses Artikels an.
Bergi

7

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 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 des Umgangs mit Ausnahmen ist besonders gut.

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

RSVP ist eine leichtgewichtige 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 jetzt Open Source .


1
+1. Dies ist das erste Beispiel, das ich gesehen habe und das für mich sinnvoll und intuitiv zu bedienen ist. Irgendwie kann mein Gehirn nicht alle deferredsund resolveund deferred.promise.thenund Vordefinitionen promiseActionsin der beliebten Q-Bibliotheksdokumentation analysieren . Gibt es eine Chance, dass Sie etwas so Unkompliziertes für Node.js wissen ?
Redsandro

1
@noel, danke, dass Sie den obigen Link geteilt haben. Es ist eine ausgezeichnete Einführungsserie für Versprechen, und ich stimme zu, dass die WinJS-Besonderheiten irrelevant sind, da der Gesamtansatz / das Thema universell ist.
Arcseldon

Schönes Beispiel. Außerdem habe ich Ihren ersten Link
repariert,

5

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

Die Bluebird- Bibliothek implementiert Versprechen und bietet Ihnen großartige Long-Stack-Traces, ist sehr schnell und warnt vor nicht erfassten Fehlern. Laut http://bluebirdjs.com/docs/benchmarks.html ist es außerdem schneller und benötigt weniger Speicher als die anderen Versprechen-Bibliotheken


4

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 vorliegen:

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

erfüllt :: Dies bedeutet, dass das Versprechen erfüllt wurde, dass der durch das Versprechen dargestellte Wert zur Verwendung bereit ist.

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 Versprechungen 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 Versprechen-Objekt initialisiert wurde.

  2. Auflösung :: Auflösung 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. Er wird verwendet, wenn die Executor-Funktion fehlschlägt. Der Fehlergrund kann an die Ablehnung übergeben werden.

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

Referenz :: Versprechen


0

Ich habe mich kürzlich auch mit Versprechungen in node.js befasst. Bisher scheint das when.js aufgrund seiner Geschwindigkeit und Ressourcennutzung der richtige Weg zu sein, aber die Dokumentation zu q.js hat mir ein viel besseres Verständnis gegeben. Verwenden Sie also when.js, aber die q.js-Dokumente, 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 möglicherweise irgendwann bereitstellt. Ein Versprechen kann auch als Proxy für ein entferntes Objekt verwendet werden, um die Latenz zu überwinden.


0

Das Promise-Objekt repräsentiert den Abschluss oder den Fehler einer asynchronen Operation.

Um ein Versprechen umzusetzen, benötigen Sie zwei Teile:

1. Versprechen erstellen:

Der Versprechen-Konstruktor akzeptiert eine Funktion namens Executor, bei der zwei Parameter aufgelöst und zurückgewiesen werden.

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

2. Umgang mit Versprechen:

Das Promise-Objekt verfügt über drei Methoden zum Behandeln von Promise-Objekten: -

1.Promise.prototype.catch (onRejected)

2.Promise.prototype.then (onFullfiled)

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

example.then((data) =>{
  //handles resolved data
  console.log(data); //prints success     
}).catch((err) => {
  //handles rejected error 
  console.log(err);  //prints error
})
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.