Wann wird der Hauptteil eines Promise-Konstruktorrückrufs ausgeführt?
Lesezeit: 5 Minuten
Kevin
Angenommen, ich habe den folgenden Code, der a erstellt Promise:
function doSomethingAsynchronous() {
return new Promise((resolve) => {
const result = doSomeWork();
setTimeout(() => {
resolve(result);
}), 100);
});
}
Zu welchem Zeitpunkt ist doSomeWork() genannt? Ist es unmittelbar danach oder als Promise ist konstruiert? Wenn nicht, muss ich noch etwas explizit tun, um sicherzustellen, dass der Rückruf ausgeführt wird?
Es spielt keine Rolle: Wenn Sie die Reihenfolge der Vorgänge erzwingen müssen, tun Sie dies explizit. Verschiedene Implementierungen verarbeiten Versprechen mit geringfügigen Unterschieden im Verhalten (z. B. Bluebird vs. Native Map).
– ssube
8. Februar 2017 um 16:52
Dies kann helfen, die Dinge zu erklären: stackoverflow.com/questions/42031051/…. Es behandelt eine etwas kompliziertere Situation (ein Versprechen innerhalb eines Versprechens), deckt aber definitiv ab, was hier vor sich geht, einschließlich dessen, was passiert, wenn ein Versprechen vor dem gelöst wird .then() Handler sind beigefügt.
– jfriend00
8. Februar 2017 um 17:41
Bitte schließen Sie diese Frage nicht als Duplikat einer Frage, die nur schlechte Antworten hat. Und NEINdies ist nicht von der Implementierung abhängig, sondern spezifiziert.
– Denys Séguret
14. September 2018 um 15:09 Uhr
Mögliches Duplikat von Wird der Promise-Konstruktor-Rückruf asynchron ausgeführt?
Die Executor-Funktion wird sofort von der Promise-Implementierung ausgeführt und übergibt Auflösungs- und Ablehnungsfunktionen (der Executor wird aufgerufen, bevor der Promise-Konstruktor überhaupt das erstellte Objekt zurückgibt).
Dies ist in der ECMAScript-Spezifikation definiert (natürlich ist es schwieriger zu lesen …) Hier (Schritt 9 ab dieser Bearbeitung zeigt, dass der Executor synchron aufgerufen wird):
Sei Vollendung Vollendung(Call(executor, undefiniert, « resolvingFunctions.[[Resolve]], auflösende Funktionen.[[Reject]]»)).
(meine Betonung)
Diese Garantie kann wichtig sein, wenn Sie beispielsweise mehrere Zusagen vorbereiten, an die Sie dann weitergeben all oder raceoder wenn Ihre Ausführenden synchrone Nebenwirkungen haben.
Sofort ist verwirrend. Der Testamentsvollstrecker wird wirklich aufgerufen synchron durch den Promise-Konstruktor.
– Paläo
28. September 2017 um 15:11 Uhr
Es scheint, dass MDN und die ES-Spezifikation das nicht mehr sagen, aber ich denke, Sie können immer noch davon ausgehen, dass es synchron läuft, da die Erwähnungen in den Schritten 1 bis 11 ein Versprechen zurückgeben, das Sie synchron zurückerhalten. Es wird nicht erwähnt, dass es asynchron ausgeführt wird oder irgendwo in die Warteschlange gestellt wird PerformPromiseThen sagt „FulfillReaction als letztes Element von … anhängen“.
– dosentmatter
26. Januar 2021 um 6:56
Eine Ergänzung: Es wird sofort (synchron) ausgeführt, aber then() ruft seinen Rückruf im nächsten Tick auf (asynchron).
– OZ_
25. November 2022 um 23:49 Uhr
Ja, der Ausführungsfunktionsblock wird synchron ausgeführt. Der Rückruf der Funktion „resolve“ und „reject“ hängt jedoch von den Aufrufen „then()“ und „catch()“ ab. then() ruft also den Resolve- und Reject-Fun-Callback asynchron auf, dh er lässt sie in der Mikrotask-Warteschlange warten und führt sie aus, wenn der Klassenstapel leer ist. Wenn also then() die Auflösung und das Rreject asynsly aufruft, was nützt es, den ausführenden Funktionsblock wieder asynchron zu machen, indem man ihn in setTimeout() einschließt?
– Kondaveti Charan
18. Mai um 16:14 Uhr
Moika dreht sich um
Unten sehen Sie, dass der Textkörper sofort ausgeführt wird, indem einfach synchroner statt asynchroner Code in den Textkörper eingefügt wird:
function doSomethingAsynchronous() {
return new Promise((resolve) => {
console.log("a");
resolve("promise result");
});
}
doSomethingAsynchronous();
console.log("b");
Das Ergebnis zeigt, dass der Versprechenstext sofort ausgeführt wird (bevor „b“ gedruckt wird).
Das Ergebnis des Versprechens bleibt erhalten und kann beispielsweise für einen „Dann“-Aufruf freigegeben werden:
function doSomethingAsynchronous() {
return new Promise((resolve) => {
console.log("a");
resolve("promise result");
});
}
doSomethingAsynchronous().then(function(pr) {
console.log("c:" + pr);
});
console.log("b");
Ergebnis:
a
b
c:promise result
Das Gleiche gilt für asynchronen Code im Körper, mit Ausnahme der unbestimmten Verzögerung, bevor das Versprechen erfüllt wird und „dann“ aufgerufen werden kann (Punkt c). So a Und b würde sobald gedruckt werden doSomethingAsynchronous() kehrt aber zurück c erscheint nur, wenn das Versprechen erfüllt ist (wird „resolve“ genannt).
Was auf den ersten Blick seltsam aussieht, sobald der Anruf erfolgt ist then hinzugefügt wird, ist das b wird vorher gedruckt c auch wenn alles synchron ist.
Sicherlich a würde dann drucken c und schlussendlich b?
Der Grund warum a, b Und c In dieser Reihenfolge werden gedruckt, da es egal ist, ob sich der Code im Körper befindet async oder syncDie then Die Methode wird von immer asynchron aufgerufen Promise.
In meinem Kopf stelle ich mir das vor then Methode, die von so etwas wie aufgerufen wird setTimeout(()=>{then(pr)},0) im Promise einmal resolve wird genannt. Das heißt, der aktuelle Ausführungspfad muss abgeschlossen sein, bevor die Funktion übergeben wird then wird durchgeführt.
Aus dem nicht ersichtlich Promise Spezifikation, warum macht es das?
Ich vermute, dass dadurch ein konsistentes Verhalten hinsichtlich des Zeitpunkts sichergestellt wird then wird aufgerufen (immer nachdem der aktuelle Ausführungsthread beendet ist), was vermutlich dazu dient, mehrere zuzulassen Promises müssen gestapelt/aneinandergekettet werden, bevor alle losgelegt werden then ruft nacheinander an.
Eisgurke
Ja, wenn Sie eine konstruieren Promise Der erste Parameter wird sofort ausgeführt.
Im Allgemeinen würde man a nicht wirklich verwenden promise So wie Sie es getan haben, wäre es wie bei Ihrer aktuellen Implementierung immer noch synchron.
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);
});
}
Der setTimeout Die Methode würde die Funktion dann zum nächstmöglichen Zeitpunkt aufrufen, wenn die Ereigniswarteschlange frei ist
Die Executor-Funktion wird sofort von der Promise-Implementierung ausgeführt und übergibt Auflösungs- und Ablehnungsfunktionen (der Executor wird aufgerufen, bevor der Promise-Konstruktor überhaupt das erstellte Objekt zurückgibt).
Betrachten Sie den folgenden Code:
let asyncTaskCompleted = true
const executorFunction = (resolve, reject) => {
console.log("This line will be printed as soon as we declare the promise");
if (asyncTaskCompleted) {
resolve("Pass resolved Value here");
} else {
reject("Pass reject reason here");
}
}
const myPromise = new Promise(executorFunction)
Wenn wir den obigen Code ausführen, executorFunction wird automatisch aufgerufen, sobald wir das bekannt geben Promiseohne dass wir es explizit aufrufen müssen.
14541700cookie-checkWann wird der Hauptteil eines Promise-Konstruktorrückrufs ausgeführt?yes
ECMAScript, 25.4.3.1
Promise(executor)
-> Schritt 9– Andreas
8. Februar 2017 um 16:49 Uhr
Es spielt keine Rolle: Wenn Sie die Reihenfolge der Vorgänge erzwingen müssen, tun Sie dies explizit. Verschiedene Implementierungen verarbeiten Versprechen mit geringfügigen Unterschieden im Verhalten (z. B. Bluebird vs. Native Map).
– ssube
8. Februar 2017 um 16:52
Dies kann helfen, die Dinge zu erklären: stackoverflow.com/questions/42031051/…. Es behandelt eine etwas kompliziertere Situation (ein Versprechen innerhalb eines Versprechens), deckt aber definitiv ab, was hier vor sich geht, einschließlich dessen, was passiert, wenn ein Versprechen vor dem gelöst wird
.then()
Handler sind beigefügt.– jfriend00
8. Februar 2017 um 17:41
Bitte schließen Sie diese Frage nicht als Duplikat einer Frage, die nur schlechte Antworten hat. Und NEINdies ist nicht von der Implementierung abhängig, sondern spezifiziert.
– Denys Séguret
14. September 2018 um 15:09 Uhr
Mögliches Duplikat von Wird der Promise-Konstruktor-Rückruf asynchron ausgeführt?
– Bergi
27. Juli 2019 um 16:42 Uhr