async function
BaselineWidely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since April 2017.
Dieasync function
-Deklaration erstellt eineBinding einer neuen asynchronen Funktion mit einem gegebenen Namen. Dasawait
-Schlüsselwort ist innerhalb des Funktionskörpers erlaubt, was ermöglicht, dass asynchrones, auf Versprechen basierendes Verhalten in einem saubereren Stil geschrieben wird, und die Notwendigkeit vermieden wird, Versprechensketten explizit zu konfigurieren.
Sie können auch asynchrone Funktionen mit demasync function
Ausdruck definieren.
Probieren Sie es aus
function resolveAfter2Seconds() { return new Promise((resolve) => { setTimeout(() => { resolve("resolved"); }, 2000); });}async function asyncCall() { console.log("calling"); const result = await resolveAfter2Seconds(); console.log(result); // Expected output: "resolved"}asyncCall();
Syntax
async function name(param0) { statements}async function name(param0, param1) { statements}async function name(param0, param1, /* …, */ paramN) { statements}
Hinweis:Es darf kein Zeilenumbruch zwischenasync
undfunction
sein, sonst wird ein Semikolonautomatisch eingefügt, was dazu führt, dassasync
zu einem Bezeichner wird und der Rest zu einerfunction
-Deklaration.
Parameter
name
Der Name der Funktion.
param
OptionalDer Name eines formalen Parameters für die Funktion. Für die Syntax der Parameter siehe dasFunktions-Referenz.
statements
OptionalDie Anweisungen, die den Körper der Funktion bilden. Der
await
-Mechanismus kann verwendet werden.
Beschreibung
Eineasync function
-Deklaration erstellt einAsyncFunction
-Objekt. Jedes Mal, wenn eine asynchrone Funktion aufgerufen wird, gibt sie ein neuesPromise
zurück, das mit dem Wert aufgelöst wird, der von der asynchronen Funktion zurückgegeben wird, oder mit einer Ausnahme abgelehnt wird, die innerhalb der asynchronen Funktion nicht abgefangen wird.
Asynchrone Funktionen können null oder mehrawait
-Ausdrücke enthalten. Await-Ausdrücke lassen versprechensbasierte Funktionen so verhalten, als wären sie synchron, indem sie die Ausführung bis zur Erfüllung oder Ablehnung des zurückgegebenen Versprechens aussetzen. Der erfüllte Wert des Versprechens wird als Rückgabewert des Await-Ausdrucks behandelt. Der Gebrauch vonasync
undawait
ermöglicht die Verwendung gewöhnlichertry
/catch
-Blöcke um asynchronen Code.
Hinweis:Dasawait
-Schlüsselwort ist nur innerhalb von asynchronen Funktionen in regulärem JavaScript-Code gültig. Wenn Sie es außerhalb des Körpers einer asynchronen Funktion verwenden, erhalten Sie einenSyntaxError
.
await
kann eigenständig mitJavaScript-Modulen verwendet werden.
Hinweis:Der Zweck vonasync
/await
ist die Vereinfachung der Syntaxdie zur Nutzung von Promise-basierten APIs notwendig ist. Das Verhaltenvonasync
/await
ist ähnlich wie die Kombination vonGeneratoren undPromises.
Asynchrone Funktionen geben immer ein Versprechen zurück. Wenn der Rückgabewert einer asynchronen Funktionnicht explizit ein Promise ist, wird es implizit in ein Promise gehüllt.
Betrachten Sie zum Beispiel folgenden Code:
async function foo() { return 1;}
Er ist ähnlich wie:
function foo() { return Promise.resolve(1);}
Beachten Sie, dass selbst wenn der Rückgabewert einer asynchronen Funktion so behandelt wird, als sei er inPromise.resolve
gewickelt, sie nicht gleich sind. Eine asynchrone Funktion wird einen anderenVerweis zurückgeben, wohingegenPromise.resolve
denselben Verweis zurückgibt, wenn der gegebene Wert ein Promise ist. Dies kann ein Problem sein, wenn Sie die Gleichheit eines Versprechens und eines Rückgabewerts einer asynchronen Funktion überprüfen möchten.
const p = new Promise((res, rej) => { res(1);});async function asyncReturn() { return p;}function basicReturn() { return Promise.resolve(p);}console.log(p === basicReturn()); // trueconsole.log(p === asyncReturn()); // false
Der Körper einer asynchronen Funktion kann so betrachtet werden, dass er durch null oder mehr await-Ausdrücke aufgeteilt wird. Top-Level-Code, bis einschließlich des ersten Await-Ausdrucks (falls vorhanden), wird synchron ausgeführt. Auf diese Weise wird eine asynchrone Funktion ohne einen Await-Ausdruck synchron ausgeführt. Ist jedoch ein Await-Ausdruck im Funktionskörper vorhanden,wird die asynchrone Funktion immer asynchron abgeschlossen.
Zum Beispiel:
async function foo() { await 1;}
Er ist ebenfalls gleichbedeutend mit:
function foo() { return Promise.resolve(1).then(() => undefined);}
Code nach jedem Await-Ausdruck kann so betrachtet werden, als würde er in einem.then
Rückruf existieren. Auf diese Weise wird eine Versprechenskette mit jedem Wiedereintrittin die Funktion progressiv aufgebaut. Der Rückgabewert bildet das letzte Glied in der Kette.
Im folgenden Beispiel warten wir nacheinander auf zwei Versprechen. Der Fortschritt bewegt sich durchdie Funktionfoo
in drei Phasen.
- Die erste Zeile des Körpers der Funktion
foo
wird synchron ausgeführt,mit dem Await-Ausdruck, der mit dem ausstehenden Versprechen konfiguriert ist. Der Fortschritt durchfoo
wird dann ausgesetzt und die Kontrolle wird an die Funktion, diefoo
aufgerufen hat, zurückgegeben. - Einige Zeit später, wenn das erste Versprechen entweder erfüllt oder abgelehnt wurde,wird die Kontrolle zurück an
foo
gegeben. Das Ergebnis der ersten Versprechens-Erfüllung(falls es nicht abgelehnt wurde) wird vom Await-Ausdruck zurückgegeben. Hier wird1
result1
zugewiesen. Der Fortschritt geht weiter und der zweite Await-Ausdruckwird ausgewertet. Wieder wird der Fortschritt durchfoo
unterbrochen und die Kontrolle wirdzurückgegeben. - Einige Zeit später, wenn das zweite Versprechen entweder erfüllt oder abgelehnt wird,wird die Kontrolle erneut an
foo
gegeben. Das Ergebnis der zweiten Versprechensauflösung wirdvom zweiten Await-Ausdruck zurückgegeben. Hier wird2
result2
zugewiesen. Die Kontrolle geht zum Rückgabewert-Ausdruck (falls vorhanden). Der Standard-Rückgabewert vonundefined
wird als der Auflösungswert desaktuellen Versprechens zurückgegeben.
async function foo() { const result1 = await new Promise((resolve) => setTimeout(() => resolve("1")), ); const result2 = await new Promise((resolve) => setTimeout(() => resolve("2")), );}foo();
Beachten Sie, wie die Versprechenskette nicht auf einen Schlag aufgebaut wird. Stattdessen wird die Versprechenskettein Phasen konstruiert, da die Kontrolle nacheinander von der asynchronenFunktion abgegeben und dorthin zurückgegeben wird. Als Ergebnis müssen wir uns des Fehlerbehandlungsverhaltens bewusst sein, wenn wir mitgleichzeitigen asynchronen Operationen umgehen.
Zum Beispiel wird im folgenden Code ein unbehandelter Versprechensablehnungsfehler geworfen,selbst wenn ein.catch
-Handler weiter entlang der Versprechenskettekonfiguriert wurde. Das liegt daran, dassp2
nicht in die Versprechenskette "eingebunden" wird, bisdie Kontrolle vonp1
zurückkommt.
async function foo() { const p1 = new Promise((resolve) => setTimeout(() => resolve("1"), 1000)); const p2 = new Promise((_, reject) => setTimeout(() => reject(new Error("failed")), 500), ); const results = [await p1, await p2]; // Do not do this! Use Promise.all or Promise.allSettled instead.}foo().catch(() => {}); // Attempt to swallow all errors...
async function
-Deklarationen verhalten sich ähnlich wiefunction
-Deklarationen — sie werdengehoisted an die Spitze ihres Gültigkeitsbereichs und können überall in ihrem Gültigkeitsbereich aufgerufen werden, und sie können nur in bestimmten Kontexten neu deklariert werden.
Beispiele
Asynchrone Funktionen und Ausführungsreihenfolge
function resolveAfter2Seconds() { console.log("starting slow promise"); return new Promise((resolve) => { setTimeout(() => { resolve("slow"); console.log("slow promise is done"); }, 2000); });}function resolveAfter1Second() { console.log("starting fast promise"); return new Promise((resolve) => { setTimeout(() => { resolve("fast"); console.log("fast promise is done"); }, 1000); });}async function sequentialStart() { console.log("== sequentialStart starts =="); // 1. Start a timer, log after it's done const slow = resolveAfter2Seconds(); console.log(await slow); // 2. Start the next timer after waiting for the previous one const fast = resolveAfter1Second(); console.log(await fast); console.log("== sequentialStart done ==");}async function sequentialWait() { console.log("== sequentialWait starts =="); // 1. Start two timers without waiting for each other const slow = resolveAfter2Seconds(); const fast = resolveAfter1Second(); // 2. Wait for the slow timer to complete, and then log the result console.log(await slow); // 3. Wait for the fast timer to complete, and then log the result console.log(await fast); console.log("== sequentialWait done ==");}async function concurrent1() { console.log("== concurrent1 starts =="); // 1. Start two timers concurrently and wait for both to complete const results = await Promise.all([ resolveAfter2Seconds(), resolveAfter1Second(), ]); // 2. Log the results together console.log(results[0]); console.log(results[1]); console.log("== concurrent1 done ==");}async function concurrent2() { console.log("== concurrent2 starts =="); // 1. Start two timers concurrently, log immediately after each one is done await Promise.all([ (async () => console.log(await resolveAfter2Seconds()))(), (async () => console.log(await resolveAfter1Second()))(), ]); console.log("== concurrent2 done ==");}sequentialStart(); // after 2 seconds, logs "slow", then after 1 more second, "fast"// wait above to finishsetTimeout(sequentialWait, 4000); // after 2 seconds, logs "slow" and then "fast"// wait againsetTimeout(concurrent1, 7000); // same as sequentialWait// wait againsetTimeout(concurrent2, 10000); // after 1 second, logs "fast", then after 1 more second, "slow"
await und Parallelität
InsequentialStart
wird die Ausführung für 2 Sekunden für das ersteawait
ausgesetzt und dann nochmal eine Sekunde für das zweiteawait
. Derzweite Timer wird nicht erstellt, bis der erste bereits ausgelöst hat, sodass der Code nach 3 Sekunden beendet wird.
InsequentialWait
werden beide Timer erstellt und dannawait
ed.Die Timer laufen gleichzeitig, was bedeutet, dass der Code nach 2 statt 3 Sekunden abgeschlossen wird,d.h. dem langsamsten Timer.Dieawait
-Aufrufe laufen jedoch weiterhin in Serie, was bedeutet, dass der zweiteawait
darauf wartet, dass der erste abgeschlossen wird. In diesem Fall wird das Ergebnis desschnellsten Timers nach dem langsamsten verarbeitet.
Wenn Sie sicher andere Aufgaben ausführen möchten, nachdem zwei oder mehr Aufgaben gleichzeitig ausgeführt wurden und abgeschlossen sind, müssen Sie einen Aufruf zuPromise.all()
oderPromise.allSettled()
erwarten, bevor die Aufgabe ausgeführt wird.
Warnung:Die FunktionensequentialWait
undconcurrent1
sind funktional nicht gleichwertig.
InsequentialWait
, wenn das Versprechenfast
zurückgewiesen wird, bevor das Versprechenslow
erfüllt wird, wird ein unbehandelter Versprechensablehnungsfehlerausgelöst, unabhängig davon, ob der Aufrufer eine catch-Klausel konfiguriert hat.
Inconcurrent1
verdrahtetPromise.all
die Versprechenskettein einem Durchgang, was bedeutet, dass der Vorgang schnell fehlschlägt, unabhängig von der Reihenfolge derZurückweisungen der Versprechen, und der Fehler tritt immer innerhalb der konfiguriertenVersprechenskette auf, sodass er auf normale Weise abgefangen werden kann.
Umschreiben einer Promise-Kette mit einer asynchronen Funktion
Ein API, das einPromise
zurückgibt, wird zu einer Versprechenskette, und esteilt die Funktion in viele Teile. Betrachten Sie den folgenden Code:
function getProcessedData(url) { return downloadData(url) // returns a promise .catch((e) => downloadFallbackData(url)) // returns a promise .then((v) => processDataInWorker(v)); // returns a promise}
dieser kann mit einer einzigen asynchronen Funktion wie folgt umgeschrieben werden:
async function getProcessedData(url) { let v; try { v = await downloadData(url); } catch (e) { v = await downloadFallbackData(url); } return processDataInWorker(v);}
Alternativ können Sie das Versprechen mitcatch()
verketten:
async function getProcessedData(url) { const v = await downloadData(url).catch((e) => downloadFallbackData(url)); return processDataInWorker(v);}
In den beiden umgeschriebenen Versionen bemerken Sie, dass es nach demreturn
-Schlüsselwort keineawait
-Anweisung gibt, obwohl das auch gültig wäre: Der Rückgabewert einerasynchronen Funktion wird implizit inPromise.resolve
gewickelt - wenner nicht bereits selbst ein Versprechen ist (wie in den Beispielen).
Spezifikationen
Specification |
---|
ECMAScript® 2026 Language Specification # sec-async-function-definitions |
Browser-Kompatibilität
Siehe auch
- Funktionen Leitfaden
- Verwendung von Versprechen Leitfaden
- Funktionen
AsyncFunction
async function
Ausdruckfunction
function*
async function*
await
Promise
- Dekorieren asynchroner JavaScript-Funktionen auf innolitics.com (2016)
MDN-Feedback-Box
Diese Seite wurde automatisch aus dem Englischen übersetzt.