webentwicklung-frage-antwort-db.com.de

Wann wird der Körper eines Versprechens ausgeführt?

Angenommen, ich habe folgendes Promise:

function doSomethingAsynchronous() {
  return new Promise((resolve) => {
    const result = doSomeWork();

    setTimeout(() => {
      resolve(result);
   }), 100);
  });
}

Zu welchem ​​Zeitpunkt wird doSomeWork() aufgerufen? Ist es unmittelbar danach oder wie das Promise konstruiert ist? Wenn nicht, muss ich zusätzlich etwas tun, um sicherzustellen, dass der Rumpf von Promise ausgeführt wird?

28
Kevin

Sofort ja, nach Vorgabe.

Von dem MDN :

Die Executor-Funktion wird sofort von der Promise-Implementierung ausgeführt, wobei Auflösungs- und Zurückweisungsfunktionen übergeben werden (der Executor wird aufgerufen, bevor der Promise-Konstruktor das erstellte Objekt zurückgibt).

Hier ist es in der ECMAScript-Spezifikation (natürlich schwieriger zu lesen ...): http://www.ecma-international.org/ecma-262/6.0/#sec-promise-executor

Diese Garantie kann wichtig sein, wenn Sie beispielsweise mehrere Zusagen erstellen, die Sie dann an all oder race übergeben oder wenn Ihre Executoren synchrone Nebenwirkungen haben.

30
Denys Séguret

Ja, wenn Sie ein Promise erstellen, wird der erste Parameter sofort ausgeführt.

Im Allgemeinen würden Sie ein Versprechen nicht so verwenden, wie Sie es getan haben, da dies bei Ihrer aktuellen Implementierung immer noch synchron wäre.

Sie würden es lieber mit einem Timeout implementieren oder die Auflösungsfunktion als Teil eines Ajax-Callbacks aufrufen

function doSomethingAsynchronous() {
  return new Promise((resolve) => {
    setTimeout(function() {
      const result = doSomeWork();
      resolve(result);
    }, 0);
  });
}

Die setTimeout-Methode ruft die Funktion dann zum nächstmöglichen Zeitpunkt auf, zu dem die Ereigniswarteschlange frei ist

4
Icepickle

Aus der EcmaScript-Spezifikation http://www.ecma-international.org/ecma-262/6.0/#sec-promise-executor

Die Executor-Funktion wird sofort von der Promise-Implementierung ausgeführt und übergibt die Auflösungs- und Zurückweisungsfunktionen (der Executor wird aufgerufen, bevor der Promise-Konstruktor das erstellte Objekt überhaupt zurückgibt).

Betrachten Sie den folgenden Code:

var executorFunction = (resolve, reject) => {
    console.log("This line will be printed as soon as we declare the promise");
    if(asynkTaskCompleted){
        resolve("Pass resolved Value here");
    }else{
        reject("Pass reject reason here");
    }

}
const myPromise = new Promise(executorFunction);

Wenn wir den obigen Code ausführen, wird executorFunction automatisch aufgerufen, sobald wir das Versprechen deklarieren, ohne dass wir es explizit aufrufen müssen.

1
Himansh

Sie können von unten sehen, dass der Rumpf sofort ausgeführt wird, indem Sie anstelle von asynchronem Code synchronen Code einfügen:

function doSomethingAsynchronous() {
  return new Promise((resolve) => {
    console.log("a");
    resolve("promise result");
  });
}
doSomethingAsynchronous();console.log("b");

Das Ergebnis zeigt, dass der Versprechen-Body sofort ausgeführt wird (bevor 'b' gedruckt wird):

a
b

Das Ergebnis des Versprechens wird beibehalten, um beispielsweise für einen Aufruf "Dann" freigegeben zu werden:

doSomethingAsynchronous().then(function(pr){console.log("c:"+pr);});console.log("b");

Ergebnis:

a
b
c:promise result

Dasselbe gilt für asynchronen Code im Body, mit Ausnahme der unbestimmten Verzögerung, bevor die Zusage erfüllt wird, und "then" kann aufgerufen werden (Punkt "c"). 'A' und 'b' werden gedruckt, sobald doSomethingAsynchronous() zurückkehrt, aber 'c' erscheint nur, wenn das Versprechen erfüllt ist ('resol' wird aufgerufen).

Was an der Oberfläche seltsam aussieht, wenn der Aufruf von 'then' hinzugefügt wird, ist, dass 'b' vor 'c' gedruckt wird, auch wenn alles synchron ist. Sicher würde 'a' drucken, dann 'c' und schließlich 'b'? Der Grund, warum 'a', 'b' und 'c' in dieser Reihenfolge gedruckt werden, besteht darin, dass unabhängig davon, ob der Code im Hauptteil asynchron oder synchron ist, die 'dann'-Methode immer asynchron von der Promise aufgerufen wird. In meinen Augen stelle ich mir vor, dass die "dann" -Methode von etwas wie setTimeout(function(){then(pr);},0); in der Promise aufgerufen wird, sobald "resolve" aufgerufen wird. Das heißt Der aktuelle Ausführungspfad muss abgeschlossen sein, bevor die an 'then' übergebene Funktion ausgeführt wird. Nicht offensichtlich aus der Promise-Spezifikation, warum dies so ist. Meine Vermutung ist, dass es ein konsistentes Verhalten in Bezug auf den Aufruf von "then" (immer nach Abschluss des aktuellen Ausführungsthreads) gewährleistet, was vermutlich das Stapeln/Verketten mehrerer Promises ermöglicht, bevor alle "then" -Aufrufe nacheinander ausgelöst werden.

0
Moika Turns