for await...of
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since January 2020.
Please help us by answering a few questions.
Die for await...of
-Anweisung erstellt eine Schleife, die über asynchrone iterierbare Objekte sowie synchrone Iterables iteriert. Diese Anweisung kann nur in Kontexten verwendet werden, in denen await
verwendet werden kann, dazu gehören der Körper einer asynchronen Funktion und in einem Modul.
Probieren Sie es aus
async function* foo() {
yield 1;
yield 2;
}
(async function () {
for await (const num of foo()) {
console.log(num);
// Expected output: 1
break; // Closes iterator, triggers return
}
})();
Syntax
for await (variable of iterable)
statement
variable
-
Erhält bei jeder Iteration einen Wert aus der Sequenz. Kann entweder eine Deklaration mit
const
,let
odervar
sein oder ein Zuweisungsziel (z.B. eine zuvor deklarierte Variable, eine Objekteigenschaft oder ein Destrukturierungsmuster). Variablen, die mitvar
deklariert sind, sind nicht lokal zur Schleife, d.h. sie befinden sich im gleichen Gültigkeitsbereich wie diefor await...of
-Schleife. iterable
-
Ein asynchrones oder synchrones Iterable. Die Quelle der Wertsequenz, über die die Schleife arbeitet.
statement
-
Eine Anweisung, die bei jeder Iteration ausgeführt wird. Kann
variable
referenzieren. Sie können eine Blockanweisung verwenden, um mehrere Anweisungen auszuführen.
Beschreibung
Wenn eine for await...of
-Schleife über ein Iterable iteriert, wird zunächst die [Symbol.asyncIterator]()
-Methode des Iterables abgerufen und aufgerufen, was einen asynchronen Iterator zurückgibt. Falls die @asyncIterator
-Methode nicht existiert, wird nach einer [Symbol.iterator]()
-Methode gesucht, die einen synchronen Iterator zurückgibt. Der zurückgegebene synchrone Iterator wird dann in einen asynchronen Iterator umgewandelt, indem jedes von den next()
, return()
und throw()
-Methoden zurückgegebene Objekt in ein aufgelöstes oder abgelehntes Promise gewrappt wird, wobei die value
-Eigenschaft aufgelöst wird, wenn sie ebenfalls ein Promise ist. Die Schleife ruft dann wiederholt die next()
-Methode des endgültigen asynchronen Iterators auf und wartet auf das zurückgegebene Promise, wodurch die Wertsequenz erzeugt wird, die variable
zugewiesen wird.
Eine for await...of
-Schleife endet, wenn der Iterator abgeschlossen ist (das gewartete next()
-Ergebnis ist ein Objekt mit done: true
). Wie bei anderen Schleifenanweisungen können Sie Steuerflussanweisungen innerhalb von statement
verwenden:
break
stoppt die Ausführung vonstatement
und geht zur ersten Anweisung nach der Schleife.continue
stoppt die Ausführung vonstatement
und geht zur nächsten Iteration der Schleife.
Wenn die for await...of
-Schleife frühzeitig beendet wurde (z.B. ein break
-Statement wird angetroffen oder ein Fehler wird geworfen), wird die return()
-Methode des Iterators aufgerufen, um eventuelle Bereinigungen vorzunehmen. Das zurückgegebene Promise wird gewartet, bevor die Schleife endet.
for await...of
funktioniert im Allgemeinen genauso wie die for...of
-Schleife und teilt viele der gleichen Syntax und Semantik. Es gibt einige Unterschiede:
for await...of
funktioniert sowohl mit synchronen als auch asynchronen Iterables, währendfor...of
nur mit synchronen Iterables arbeitet.for await...of
kann nur in Kontexten verwendet werden, in denenawait
verwendet werden kann, dazu gehören der Körper einer asynchronen Funktion und in einem Modul. Auch wenn das Iterable synchron ist, wartet die Schleife dennoch den Rückgabewert bei jeder Iteration ab, was zu einer langsameren Ausführung aufgrund des wiederholten Promise-Unwrappings führt.- Wenn das
iterable
ein synchrones Iterable ist, das Promises liefert, würdefor await...of
eine Folge von aufgelösten Werten erzeugen, währendfor...of
eine Folge von Promises erzeugen würde. (Vorsicht jedoch bei der Fehlerbehandlung und Bereinigung — siehe Über synchron iterierbare und Generatoren iterieren) - Für
for await...of
kannvariable
der Bezeichnerasync
sein (z.B.for await (async of foo)
);for...of
verbietet diesen Fall.
Beispiele
Über asynchrone Iterables iterieren
Sie können auch über ein Objekt iterieren, das explizit das asynchrone Iterierprotokoll implementiert:
const LIMIT = 3;
const asyncIterable = {
[Symbol.asyncIterator]() {
let i = 0;
return {
next() {
const done = i === LIMIT;
const value = done ? undefined : i++;
return Promise.resolve({ value, done });
},
return() {
// This will be reached if the consumer called 'break' or 'return' early in the loop.
return { done: true };
},
};
},
};
(async () => {
for await (const num of asyncIterable) {
console.log(num);
}
})();
// 0
// 1
// 2
Über asynchrone Generatoren iterieren
Da die Rückgabewerte von asynchronen Generatorfunktionen dem asynchronen Iterierprotokoll entsprechen, können sie mit for await...of
durchlaufen werden.
async function* asyncGenerator() {
let i = 0;
while (i < 3) {
yield i++;
}
}
(async () => {
for await (const num of asyncGenerator()) {
console.log(num);
}
})();
// 0
// 1
// 2
Für ein konkreteres Beispiel über das Iterieren eines asynchronen Generators mit for await...of
, überlegen Sie, über Daten von einer API zu iterieren.
Dieses Beispiel erstellt zuerst ein asynchrones Iterable für einen Datenstrom und verwendet es dann, um die Größe der Antwort von der API zu finden.
async function* streamAsyncIterable(stream) {
const reader = stream.getReader();
try {
while (true) {
const { done, value } = await reader.read();
if (done) return;
yield value;
}
} finally {
reader.releaseLock();
}
}
// Fetches data from URL and calculates response size using the async generator.
async function getResponseSize(url) {
const response = await fetch(url);
// Will hold the size of the response, in bytes.
let responseSize = 0;
// The for-await-of loop. Async iterates over each portion of the response.
for await (const chunk of streamAsyncIterable(response.body)) {
// Incrementing the total response length.
responseSize += chunk.length;
}
console.log(`Response Size: ${responseSize} bytes`); // "Response Size: 1071472"
return responseSize;
}
getResponseSize("https://jsonplaceholder.typicode.com/photos");
Über synchrone Iterables und Generatoren iterieren
Die for await...of
-Schleife konsumiert auch synchrone Iterables und Generatoren. In diesem Fall wartet sie intern auf die ausgegebenen Werte, bevor sie ihnen die Schleifenkontrollvariable zuweist.
function* generator() {
yield 0;
yield 1;
yield Promise.resolve(2);
yield Promise.resolve(3);
yield 4;
}
(async () => {
for await (const num of generator()) {
console.log(num);
}
})();
// 0
// 1
// 2
// 3
// 4
// compare with for-of loop:
for (const numOrPromise of generator()) {
console.log(numOrPromise);
}
// 0
// 1
// Promise { 2 }
// Promise { 3 }
// 4
Hinweis:
Beachten Sie, dass das Ausgeben von abgelehnten Promises aus einem synchronen Generator for await...of
bei der Konsumierung des abgelehnten Promises wirft und NICHT die finally
-Blöcke innerhalb dieses Generators aufruft. Dies kann unerwünscht sein, wenn Sie einige zugewiesene Ressourcen mit try/finally
freigeben müssen.
function* generatorWithRejectedPromises() {
try {
yield 0;
yield 1;
yield Promise.resolve(2);
yield Promise.reject(3);
yield 4;
throw 5;
} finally {
console.log("called finally");
}
}
(async () => {
try {
for await (const num of generatorWithRejectedPromises()) {
console.log(num);
}
} catch (e) {
console.log("caught", e);
}
})();
// 0
// 1
// 2
// caught 3
// compare with for-of loop:
try {
for (const numOrPromise of generatorWithRejectedPromises()) {
console.log(numOrPromise);
}
} catch (e) {
console.log("caught", e);
}
// 0
// 1
// Promise { 2 }
// Promise { <rejected> 3 }
// 4
// caught 5
// called finally
Damit die finally
-Blöcke eines synchronen Generators immer aufgerufen werden, verwenden Sie die entsprechende Form der Schleife — for await...of
für den asynchronen Generator und for...of
für den synchronen — und warten Sie innerhalb der Schleife explizit auf ausgegebene Promises.
(async () => {
try {
for (const numOrPromise of generatorWithRejectedPromises()) {
console.log(await numOrPromise);
}
} catch (e) {
console.log("caught", e);
}
})();
// 0
// 1
// 2
// caught 3
// called finally
Spezifikationen
Specification |
---|
ECMAScript® 2025 Language Specification # sec-for-in-and-for-of-statements |
Browser-Kompatibilität
Report problems with this compatibility data on GitHubdesktop | mobile | server | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
for await...of |
Legend
Tip: you can click/tap on a cell for more information.
- Full support
- Full support