Wie erhalte ich Zugang zu früheren Versprechen, die Ergebnisse in eine .dann() Kette?
Habe ich umstrukturiert, meinen code zu verspricht, und baute eine wunderschöne lange flach Versprechen Kette, bestehend aus mehreren .then()
Rückrufe. Am Ende will ich wieder einige composite-Wert, und benötigen Zugriff auf mehrere intermediate Versprechen Ergebnisse. Jedoch ist die Auflösung der Werte aus der Mitte der Sequenz sind nicht im Umfang in den letzten Rückruf, wie kann ich auf Sie zugreifen?
function getExample() {
return promiseA(…).then(function(resultA) {
//Some processing
return promiseB(…);
}).then(function(resultB) {
//More processing
return //How do I gain access to resultA here?
});
}
Diese Frage ist wirklich interessant und auch wenn es markiert ist
Ich habe gerade herausgefunden, wurden alle Ihre rep ist aus 😉
javascript
ist es relevant, in einer anderen Sprache. Ich verwende nur die "break the chain" Antwort in java und jdeferredIch habe gerade herausgefunden, wurden alle Ihre rep ist aus 😉
InformationsquelleAutor Bergi | 2015-01-31
Du musst angemeldet sein, um einen Kommentar abzugeben.
Brechen Sie die Kette
Wenn Sie brauchen, um auf die intermediate-Werte in Ihrer Kette, Sie sollten teilen Sie Ihre Kette abgesehen, die in den einzelnen Stücken, die Sie brauchen. Anstelle der Anbringung einer callback und irgendwie versuchen, verwenden Sie den parameter mehrmals an, befestigen Sie mehrere Rückrufe die gleichen Versprechen - überall dort, wo Sie das Ergebnis Wert. Vergessen Sie nicht, eine Versprechen gerade steht (proxies) Wert in der Zukunft! Neben der Ableitung ein Versprechen von der anderen in einer linearen Kette, verwenden Sie die Versprechen combinators, die gegeben werden, um Sie von Ihrer Bibliothek zu bauen, das Ergebnis Wert.
Dadurch wird eine sehr einfache Ablaufsteuerung, klare Komposition von Funktionen und daher leicht Modularisierung.
Anstelle des Parameters destructuring in der callback-nach
Promise.all
, die nur verfügbar wurde mit ES6, in ES5 diethen
nennen würde ersetzt werden durch eine raffinierte Helfer-Methode, wurde von vielen Versprechen Bibliotheken (Q, Bluebird, wenn, ...):.spread(function(resultA, resultB) { …
.Bluebird verfügt auch über eine dedizierte
join
- Funktion zu ersetzen, diePromise.all
+spread
Kombination mit einer einfacher (und effizienter) zu gestalten:Es gibt keine Funktionen in das array, das sind Verheißungen.
promiseA
undpromiseB
sind das (Versprechen der Rückgabe) Funktionen hier.hier ist eine demo - jsfiddle.net/5t6L8dur
Nie sagte, es sei 🙂 Diese Antwort wurde geschrieben in dem ES5 Alter, wo keine Versprechungen waren in der Norm, und
spread
war super nützlich in diesem Muster. Weitere moderne Lösungen sehen die akzeptierte Antwort. Allerdings habe ich bereits aktualisiert die explizite-passthrough Antwort, und es gibt wirklich keinen guten Grund, nicht zu aktualisieren diese ein als gut.Nein, Sie sollten das nicht tun,, es würde ärger mit Ablehnungen.
InformationsquelleAutor Bergi
ECMAScript Harmony
Natürlich, dieses problem wurde erkannt, die durch die Sprache-Designern sowie. Sie hat eine Menge Arbeit, und die async-Funktionen Vorschlag schaffte es endlich in
ECMAScript 8
Brauchen Sie nicht einen einzigen
then
Aufruf oder die callback-Funktion nicht mehr, wie in einem asynchronen Funktion (, die eine Zusage zurückgibt, wenn Sie aufgerufen wird), können Sie einfach warten, für verspricht zu lösen direkt. Es verfügt auch über beliebige Kontrollstrukturen wie Bedingungen, Schleifen und try-catch-Klauseln, aber für die Bequemlichkeit, die wir nicht brauchen Sie hier:ECMAScript 6
Während wir warteten, ES8, das haben wir schon getan verwenden eine sehr ähnliche syntax. ES6 kam mit generator-Funktionen, mit denen zu brechen, die die Ausführung auseinander in Stücke zu willkürlich platziert
yield
keywords. Diese Scheiben können ausgeführt werden, nachdem jeder andere, unabhängig voneinander, sogar asynchron - und das ist genau das, was wir tun, wenn wir warten wollen für ein Versprechen, Auflösung, bevor Sie den nächsten Schritt.Gibt es engagierte Bibliotheken (wie co oder task.js), aber auch viele Versprechen Bibliotheken haben Hilfsfunktionen ( Q , Bluebird, wenn, ...), die das async-Schritt-für-Schritt-Ausführung für Sie, wenn Sie geben Sie eine generator-Funktion, die Erträge verspricht.
Dies hat nicht immer funktioniert Node.js seit der version 4.0, auch ein paar Browser (oder deren dev-Editionen) unterstützt hat, generator-syntax relativ früh.
ECMAScript 5
Jedoch, wenn Sie wollen/müssen, werden rückwärts-kompatibel, Sie können nicht verwenden, die ohne einen transpiler. Beide generator-Funktionen und async-Funktionen werden unterstützt, indem die aktuellen Werkzeuge finden Sie zum Beispiel in der Dokumentation von Babel auf Generatoren und async-Funktionen.
Und dann gibt es auch viele andere compile -, um-JS Sprachen
speziell zur Lockerung der asynchronen Programmierung. Sie in der Regel verwenden Sie eine syntax wie die
await
(z.B. Iced CoffeeScript), aber es gibt auch andere, die über ein Haskell-wiedo
-notation (z.B. LatteJs, der monadischen, PureScript oder LispyScript).brauchen Sie, um zu erwarten das async-Funktion unter anderem getExample() von außerhalb des Kodex?
Ja,
getExample
ist noch eine Funktion, die eine Zusage zurückgibt, funktioniert genau wie die Funktionen in den anderen Antworten, aber mit schöneren syntax. Sie konnteawait
einen Anruf in einem anderenasync
Funktion, oder man könnte die Kette.then()
zu Ihrem Ergebnis.Ich bin neugierig, warum haben Sie die Antwort auf Ihre eigene Frage sofort nach zu Fragen? Es gibt einige gute Diskussion hier, aber ich bin neugierig. Vielleicht finden Sie Ihre Antworten auf Ihre eigenen nach zu Fragen?
Ich stellte die ganze Diskussion über Zweck, als eine kanonische doppelte Ziel
InformationsquelleAutor Bergi
Synchrone Inspektion
Zuweisung verspricht-für-später-bei Bedarf-von Werten zu Variablen und dann immer Ihren Wert über synchron-Inspektion. Das Beispiel verwendet bluebird ist
.value()
- Methode, aber viele Bibliotheken bieten ähnliche Methode.Dies kann verwendet werden, für so viele Werte, wie Sie möchten:
Äh, "minimale Abhängigkeit von Bibliotheks-features"? Synchron-Inspektion ist ein Bibliotheks-feature, und ein ziemlich non-standard zu Booten.
Ich glaube er meinte-Bibliothek Besonderheiten
InformationsquelleAutor Esailija
Verschachteln (und) Verschlüsse
Verwendung von Verschlüssen für die Aufrechterhaltung der Gültigkeitsbereich von Variablen (in unserem Fall, die Erfolgs-callback-Funktion Parameter) ist die Natürliche JavaScript-Lösung. Mit dem Versprechen, wir können beliebig nest und glätten
.then()
Rückrufe - Sie sind semantisch äquivalent, mit der Ausnahme für den Anwendungsbereich der inneren.Natürlich ist das Gebäude eine Einbuchtung der Pyramide. Wenn die Einrückung ist immer zu groß, können Sie immer noch gelten die alten Werkzeuge, die gegen die pyramid of doom: Modularisieren, mit extra benannten Funktionen, und glätten Sie das Versprechen Kette, sobald Sie brauchen nicht eine variable mehr.
In der Theorie kann man immer vermeiden, mehr als zwei Ebenen der Verschachtelung, indem alle Sperrungen explizit), in der Praxis möglichst viele so vernünftig sind.
Können Sie auch die Hilfsfunktionen für diese Art von partielle Anwendung, wie
_.partial
aus Unterstreichen/lodash oder die native.bind()
Methode, weiter zu verringern Einzug:Das ist genau der
bind
Funktion in Monaden. Haskell bietet syntaktischen Zucker (do-notation), um es so Aussehen wie async/await syntax.Schön zu Lesen! Das Muster ist gut lesbar und war eine große Hilfe. Danke!!!
InformationsquelleAutor Bergi
Explizite pass-through
Ähnlich Verschachtelung der Rückrufe, diese Technik beruht auf Verschlüsse. Doch, die Kette bleibt flach - statt der übergabe nur das Letzte Ergebnis einige state-Objekt übergeben, für jeden Schritt. Diese Status-Objekte, sammeln Sie die Ergebnisse der vorherigen Aktionen, indem Sie alle Werte, die benötigt werden, später wieder plus das Ergebnis der aktuellen Aufgabe.
Hier, der kleine Pfeil
b => [resultA, b]
ist die Funktion, schließt überresultA
, und übergibt ein array von beide Ergebnisse an den nächsten Schritt. Was nutzt die parameter destructuring syntax zu brechen, es in einzelne Variablen wieder.Bevor destructuring wurde mit ES6, eine raffinierte Helfer-Methode genannt
.spread()
wurde von vielen Versprechen Bibliotheken (Q, Bluebird, wenn, ...). Es dauert eine Funktion mit mehreren Parameter - eine für jedes array-element verwendet zu werden, wie.spread(function(resultA, resultB) { …
.Natürlich, dass die Schließung nötig, hier kann weiter vereinfacht werden, indem einige Hilfsfunktionen, z.B.
Alternativ können Sie beschäftigen
Promise.all
zu produzieren, die Versprechen für das array:Und Sie vielleicht nicht nur arrays, sondern beliebig komplexe Objekte. Zum Beispiel, mit
_.verlängern
oder- Objekt.zuweisen
in einer anderen Hilfsfunktion:Während diese Struktur garantiert eine flache Kette und explicit state objects can verbessern die Klarheit, es wird langweilig werden für eine lange Kette. Vor allem, wenn Sie brauchen, der Staat nur sporadisch, Sie noch zu Durchlaufen haben, Sie durch jeden Schritt. Mit dieser festen Schnittstelle, die einzelne Rückrufe in der Kette sind ziemlich eng gekoppelt und unflexibel zu ändern. Es macht factoring einzelne Schritte schwerer und Rückrufe können nicht geliefert werden, direkt aus anderen Modulen - Sie müssen immer verpackt sein Standardcode, der kümmert sich um den Zustand. Abstract helper-Funktionen wie die oben genannten können die Schmerzen lindern ein wenig, aber es wird immer vorhanden sein.
Promise.all
sollte gefördert werden (es funktioniert nicht in ES6, wenn destructuring zu ersetzen und den Wechsel von einer.spread
zu einemthen
gibt Menschen, die oft unerwartete Ergebnisse. Als der vermehren - ich bin nicht sicher, warum Sie brauchen, um zu verwenden, ergänzen - hinzufügen von Dingen, die an das Versprechen, das Vorbild ist keine akzeptable Art und Weise zu erweitern ES6 verspricht jedenfalls, die ausgeweitet werden soll mit (derzeit nicht unterstützt) Unterklassen.Was meinst du mit "syntax weglassen
Promise.all
"? Keine der Methoden, die in dieser Antwort wird der Bruch mit ES6. Umschaltenspread
zu einem destructuringthen
sollte keine Probleme entweder. Re .der Prototyp.vermehren: ich wusste, dass jemand würde es bemerken, ich mochte nur Möglichkeiten zu erforschen, - geht, um es zu Bearbeiten aus.Durch die array-syntax, die ich meine
return [x,y]; }).spread(...
stattreturn Promise.all([x, y]); }).spread(...
würde sich nicht ändern, wenn swapping Strecke für es6 destructuring Zucker und würde auch nicht eine seltsame edge-Fall, wo die Versprechungen behandeln die Rückgabe von arrays anders als alles andere.Dies ist wahrscheinlich die beste Antwort. Versprechen sind "Functional Reactive Programming"-Licht, und dies ist oft der Lösung beschäftigt. Zum Beispiel, BaconJs, hat #combineTemplate, dass können Sie kombinieren, Ergebnisse in ein Objekt übergeben bekommt unten in der Kette
Die Antwort war geschrieben, wenn ES6 war nicht so weit verbreitet wie es heute ist. Ja, vielleicht ist es Zeit, um die swap-Beispiele
InformationsquelleAutor Bergi
Veränderlich kontextuellen Zustand
Dem trivialen (aber unelegant und eher fehlerträchtig) Lösung ist, nur eine höhere-Geltungsbereich von Variablen (zu denen alle Rückrufe in der Kette Zugriff haben) und schreiben Sie das Ergebnis Werten Sie diese, wenn Sie Sie bekommen:
Statt vieler Variablen könnte man auch ein (zunächst noch leeres) Objekt, auf dem die Ergebnisse gespeichert werden als dynamisch erzeugte Eigenschaften.
Diese Lösung hat mehrere Nachteile:
Bluebird Bibliothek fördert die Nutzung der ein Objekt übergeben wird, zusammen mit Ihre
bind()
Methode ein kontextobjekt zuweisen, um ein Versprechen Kette. Es wird im Internet von jeder callback-Funktion, die über die sonst unbrauchbarthis
- Schlüsselwort. Während Objekt-Eigenschaften sind mehr anfällig für unbemerkte Tippfehler als Variablen, das Muster ist Recht clever:Dieser Ansatz kann leicht simuliert Versprechen Bibliotheken nicht unterstützen .binden (obwohl in einer etwas ausführlicheren Art und Weise und kann nicht in einem Ausdruck verwendet werden):
.bind()
ist unnötig für die Verhinderung der memory-leakAber nicht das zurückgegeben Versprechen halten eine Referenz auf das Kontext-Objekt sonst? OK, natürlich die garbage-collection-handle es später; es ist nicht ein "Leck", es sei denn, das Versprechen ist nie entsorgt.
Ja, aber die Versprechen auch halten Bezug auf Ihre Erfüllung, Werte und Fehler Gründe... aber nichts hält Verweis auf die Verheißung, so spielt es keine Rolle
Bitte brechen Sie diese Antwort in zwei als ich fast gestimmt auf die Präambel! Ich denke, "die triviale (aber unelegant und eher fehlerträchtig) - Lösung" ist die sauberste und einfachste Lösung, denn es setzt nicht mehr auf Verschlüsse und veränderlichen Zustand als Ihres akzeptiert, selbst beantworten, ist doch einfacher. Verschlüsse sind weder global noch böse. Die Argumente gegen diesen Ansatz machen für mich keinen Sinn gegeben, der Prämisse. Was die Modularisierung Probleme kann es gegeben werden, eine "wunderbare lange, flache Versprechen Kette"?
Wie ich oben sagte, die Versprechen der "Functional Reactive Programming"-Licht. Dies ist ein anti-pattern in den FRP
InformationsquelleAutor Bergi
Ein weniger grelles spin auf "Veränderlich kontextuellen Zustand"
Mit einem lokal gültigen Objekt zu sammeln, die Zwischenergebnisse in einem Versprechen Kette ist eine vernünftige Herangehensweise an die Frage, die Sie stellte. Betrachten Sie den folgenden Codeausschnitt:
Promise
Konstruktor antipattern!Danke @Bergi, ich war gar nicht bewusst, das war ein anti-pattern, bis Sie es erwähnt!
dies ist ein guter workaround zu mildern Versprechen zugehörigen Fehler.Ich war mit ES5 und nicht möchten, fügen Sie eine weitere Bibliothek für die Arbeit mit Versprechen.
InformationsquelleAutor Jay
Knoten 7.4 unterstützt nun async/await-Anrufe mit den Eintracht-fahne.
Versuchen Sie dies:
und führen Sie die Datei mit:
node --harmony-async-await getExample.js
Einfach, wie sein kann!
InformationsquelleAutor Antoine
Anderen Antwort, mit
babel-node
version <6Mit
async - await
npm install -g [email protected]
example.js:
Führen Sie dann
babel-node example.js
und voila!Ja, habe ich, gleich nachdem ich mir geschrieben. Trotzdem, ich werde es lassen, weil es erklärt, wie man tatsächlich aufstehen und laufen mit ES7 im Gegensatz zu einfach zu sagen, dass eines Tages ES7 verfügbar sein wird.
Ach ja, sollte ich update meine Antwort zu sagen, dass die "experimentell" - plugins für diese bereits hier.
InformationsquelleAutor Antoine
Dieser Tage, die ich auch hava treffen sich einige Fragen wie Sie. Endlich finde ich eine gute Lösung mit der quesition, es ist einfach und gut zu Lesen. Ich hoffe, dass diese Ihnen helfen können.
Laut how-to-chain-javascript-promises
ok, schauen wir uns den code:
Jedes Versprechen erhalten können, wird der Vorherige Wert, was ist Ihre Bedeutung?
Werfen Sie einen Blick auf den code in der Frage. Das Ziel ist nicht, um das Ergebnis zu erhalten das Versprechen, dass
.then
aufgerufen wird, aber die Ergebnisse von vorher. E. g.thirdPromise
Zugriff auf das Ergebnis derfirstPromise
.Tut mir Leid, dass, ich weiß, Ihr Sinn nun, dies ist meine erste Antwort auf stackoverflow, bitte verzeihen Sie.
Dir ist eine tolle Idee! , die helfen können, bauen alle Ergebnisse. Zu gehen zu halten.
InformationsquelleAutor yzfdjzwl
Ich werde nicht verwenden Sie dieses Muster in meinem eigenen code, da ich nicht bin ein großer fan von der Verwendung von globalen Variablen. Aber, in eine Prise, es wird funktionieren.
Benutzer ein promisified Mongoose Modell.
In Ihrem Fall, das Muster scheint zu sein, nutzlos obwohl. Sie brauchen nicht ein
globalVar
überhaupt, nurUser.findAsync({}).then(function(users){ console.log(users); mongoose.connection.close() });
?Ich brauche es nicht persönlich, in meinem eigenen code, aber die Benutzer müssen möglicherweise mehr async in der zweiten Funktion und dann die Interaktion mit dem ursprünglichen Versprechen rufen. Aber wie erwähnt, ich ' ll werden mithilfe von Generatoren in diesem Fall. 🙂
InformationsquelleAutor Antoine
Bei der Verwendung von bluebird, die Sie verwenden können
.bind
Methode zum freigeben von Variablen in Versprechen Kette:bitte überprüfen Sie diesen link für weitere Informationen:
http://bluebirdjs.com/docs/api/promise.bind.html
InformationsquelleAutor alphakevin
einfach Weg 😀
InformationsquelleAutor Minh Giang
Ich denke, dass Sie verwenden können, hash von RSVP.
Etwas wie die folgenden :
Promise.all
Lösung, nur ein Objekt statt einem array.InformationsquelleAutor Vishu