Frage Warum benötigt der Promise-Konstruktor eine Funktion, die "resolve" aufruft, wenn sie abgeschlossen ist, aber "then" nicht - sie gibt stattdessen einen Wert zurück?


Wie ich ins Studium stürze PromiseEnglisch: www.mjfriendship.de/en/index.php?op...=view&id=167 Mein Verständnis hat auf der folgenden Frage, die ich nicht diskutiert finde, angehalten (alles, was ich finde, sind spezifische Diskussionen über die Promise Konstruktor und die Promise "thenFunktion - aber keine Diskussion, die ihre Entwurfsmuster vergleicht.


1. Die Promise Konstrukteur

Aus der MDN-Dokumentation, Wir haben diese Verwendung des Promise-Konstruktors (mit meinem Kommentar hinzugefügt):

new Promise(function(resolve, reject) { ... }); // <-- Call this Stage 1

Funktionsobjekt mit zwei Argumenten resolve und reject. Der Erste   Argument erfüllt das Versprechen, das zweite Argument lehnt es ab. Wir können   rufen Sie diese Funktionen auf, sobald unsere Operation abgeschlossen ist.


2. Die then Funktion

Weiter zum then Funktion das kann auf a Promise Objekt (das eine neue zurückgibt Promise Objekt), wir haben die folgende Funktionssignatur wie in der Dokumentation beschrieben (mit meinen Anmerkungen hinzugefügt): :

p.then(onFulfilled, onRejected);

Verkettung

Weil das then Methode gibt eine Promise zurück, die Sie dann einfach verketten können   Anrufe.

var p2 = new Promise(function(resolve, reject) {
  resolve(1); // <-- Stage 1 again
});

p2.then(function(value) {
  console.log(value); // 1
  return value + 1; // <-- Call this Stage 2
}).then(function(value) {
  console.log(value); // 2
});

Meine Frage

Aus dem obigen Codeausschnitt scheint mir klar zu sein, dass die Wert an die übergeben resolve Funktion in Stufe 1 (beim zweiten Auftreten von resolve - unter (2), oben) wird an die nächste Stufe weitergegeben (die erste then Funktion, die im selben Code-Snippet folgt). Es gibt keinen Rückgabewert auf Stufe 1.  Es ist jedoch die Rückgabewert in Stufe 2, die danach an die nächste Stufe weitergegeben wird (die zweite then Funktion).

Ist dieser Mangel an Übereinstimmung zwischen dem Designmuster für die Erstellung eines Promiseund die Verwendung der then Funktion für ein bestehendes Versprechen (das auch ein Promise), nur ein historischer Zufall (man benötigt einen Callback, aber gibt nichts zurück, und der andere gibt einen Wert zurück, ruft aber keinen Callback auf).

Oder fehlt mir ein Grund, warum die Promise Konstruktor verwendet ein anderes Designmuster als das then Funktion?


26
2017-07-09 17:13


Ursprung


Antworten:


Bergis Antwort ist ausgezeichnet und hat mir sehr geholfen. Diese Antwort ergänzt seine. Um die Beziehung zwischen den zu visualisieren Promise() Konstruktor und der then() Methode, ich habe dieses Diagramm erstellt. Ich hoffe, es hilft jemandem ... vielleicht sogar mir, ein paar Monate in der Zukunft.

Der Grundgedanke dabei ist, dass die "Executor" -Funktion an die Promise() Konstruktor setzt Aufgaben in Bewegung, die dies tun setze den Zustand der Verheißung; während die Handler, zu denen du gehst then() werden reagiere auf den Staat von der Verheißung.

Diagram: Promise() executor vs. then() method (Codebeispiele angepasst von Jake Archibalds klassisches Tutorial.)

Dies ist eine stark vereinfachte Sicht auf die Funktionsweise der Dinge und lässt viele wichtige Details aus. Aber ich denke, wenn man einen guten Überblick über den beabsichtigten Zweck behalten kann, wird es helfen, Verwirrung zu vermeiden, wenn man in die Details kommt.

Ein paar ausgewählte Details

Der Executor wird sofort aufgerufen

Ein wichtiges Detail ist, dass die Executor - Funktion an die Promise() Konstruktor wird aufgerufen sofort (bevor der Konstruktor das Versprechen zurückgibt); während die Handler-Funktionen an die übergeben then() Methode wird nicht aufgerufen bis später (wenn jemals).

Bergi hat das erwähnt, aber ich wollte es neu formulieren, ohne die Begriffe a / synchron zu benutzen, was verwirrt sein kann, wenn man nicht genau liest: Die Unterscheidung zwischen einer Funktion Berufung etwas asynchron vs gerufen werden asynchron ist in der Kommunikation leicht zu beschönigen.

resolve() ist nicht onFulfill()

Noch ein Detail, das ich betonen möchte, weil es mich für eine Weile verwirrt hat, ist das resolve() und reject() Rückrufe gingen an die Promise() Executor-Funktion des Konstruktors sind nicht die Rückrufe gingen später an die then() Methode. Dies erscheint im Nachhinein offensichtlich, aber die scheinbare Verbindung ließ mich zu lange im Kreis drehen. Es gibt definitiv eine Verbindung, aber es ist eine lose, dynamische.

Stattdessen resolve() und reject() Rückrufe sind Funktionen geliefert vom "System", und werden an die Executor - Funktion übergeben Promise Konstruktor, wenn Sie ein Versprechen erstellen. Wenn das resolve() Englisch: www.weisang.info/index.php?id=143&t...h=cfd8d8d8cf Funktion wird aufgerufen, Systemcode wird ausgeführt, der möglicherweise den Zustand des Versprechens ändert und schließlich zu einem führt onFulfilled() Callback wird asynchron aufgerufen. Denk nicht ans Telefonieren resolve() als eine enge Hülle zum Anrufen onFulfill()!


20
2018-02-02 14:39



Es besteht keine Übereinstimmung zwischen den Promise Konstruktor und der then Methode, weil sie zwei unabhängige Dinge sind, für verschiedene Zwecke konzipiert.

Das Promise Konstruktor wird nur für verwendet Promistifizierung1 asynchrone Funktionen. In der Tat, wie Sie sagen, es ist darauf aufgebaut aufrufend  resolve/reject Rückrufe zu asynchron senden Werte, und in diesem Fall gibt es keine Rückgabewerte.

Dass die Promise Konstruktor selbst nimmt diesen "Resolver" Callback (zu dem er synchron läuft) resolve und reject) ist in der Tat eine Verbesserung der älteren verzögertes Musterund Bären keine beabsichtigte Ähnlichkeit zum then Rückrufe.

var p = new Promise(function(res, rej) {    |    var def = Promise.Deferred();
    setTimeout(res, 100);                   |    setTimeout(def.resolve, 100);
});                                         |    var p = def.promise;

Das then Callbacks hingegen sind klassische asynchrone Callbacks, wobei die zusätzliche Funktion dass du kannst return von ihnen. Sie sind asynchron aufgerufen wird zu erhalten Werte.

p.then(function(val) { … });

Um die Unterschiede zusammenzufassen:

  • Promise ist ein Konstruktor, während then ist eine Methode
  • Promise nimmt einen Rückruf, während then dauert bis zu zwei
  • Promise ruft seinen Callback synchron auf, während then ruft seine Callbacks asynchron auf
  • Promise ruft immer seinen Rückruf auf,
    then kann seine Callbacks nicht aufrufen (wenn das Versprechen nicht erfüllt / abgelehnt wird)
  • Promise Übergibt die Funktionen zum Auflösen / Ablehnen einer Zusage an den Rückruf.
    thenübergibt den Ergebniswert / Zurückweisungsgrund des zugesagten Versprechens
  • Promise ruft seinen Callback zum Ausführen von Nebenwirkungen auf (Aufruf reject/resolve),
    then ruft seine Callbacks für ihre Ergebniswerte auf (zur Verkettung)

Ja, beide geben Versprechungen zurück, obwohl sie diese Eigenschaft mit vielen anderen Funktionen teilen (Promise.resolve, Promise.reject, fetch, ...). In der Tat basieren alle diese auf der gleichen vielversprechenden Konstruktion und lösen / ablehnen Fähigkeiten, die auch die Promise Konstruktor bietet, obwohl das nicht ihre primäre Aufgabe ist. then bietet grundsätzlich die Möglichkeit zum Anhängen onFulfilled/onRejected Rückrufe zu einem bestehenden Versprechen, das eher dem Promise Konstrukteur.

Dass beide Callbacks verwenden, ist nur ein Zufall - kein historischer Zufall, sondern eine Koadaption eines Sprachmerkmals.

1: Im Idealfall würden Sie dies niemals benötigen, da alle nativen asynchronen APIs Versprechungen zurückgeben


23
2017-07-09 17:32



Der ganze Sinn der Executor-Funktion des Prometheus-Konstruktors besteht darin, Auflösungs- und Ablehnungsfunktionen an Code weiterzugeben, der keine Versprechen enthält, ihn zu umbrechen und ihn so zu konvertieren, dass er ein Versprechen verwendet. Wenn Sie dies nur auf synchrone Funktionen beschränken möchten, dann könnte ja ein Rückgabewert von der Funktion verwendet worden sein, aber das wäre dumm gewesen, da der nützliche Teil darin besteht, die Resolver- und Ablehnungsfunktionen zu einem Code zu verbreiten, der später tatsächlich ausgeführt wird (Weg nach der Rückkehr), z Callbacks an einige asynchrone API übergeben.


5
2017-07-09 18:52



Inspiriert von den vorherigen Antworten (ich werde den Teil ansprechen, der für mich am verwirrendsten war):

Das resolve und reject Argumente im Promise-Konstruktor sind keine von Ihnen definierten Funktionen. Betrachten Sie sie als Hooks, die Sie in Ihren asynchronen Operationscode einbetten können (normalerweise Sie resolve mit Erfolg und Antwort reject mit Fehlergrund), so dass Javascript eine Möglichkeit hat, das Versprechen je nach dem Ergebnis Ihrer asynchronen Operation als erfüllt oder abgelehnt zu markieren; Sobald dies passiert, die entsprechende Funktion, in der Sie definiert haben then(fun1, fun2) wird ausgelöst, um das Versprechen zu konsumieren (entweder fun1(success_response) oder fun2(failure_reason), abhängig davon, ob das Versprechen erfüllt / abgelehnt wird). Schon seit fun1 und fun2 sind einfach alte JavaScript-Funktionen (sie passieren einfach das zukünftige Ergebnis Ihrer asynchronen Operation als Argumente), sie return Werte (die sein können undefined wenn Sie nicht explizit zurückkehren).

Siehe auch tolle Artikel von Mozilla:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises 

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise


1
2018-03-23 16:11