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.
Die for await...of
-Anweisung erzeugt eine Schleife, die über asynchrone Iterable-Objekte sowie synchrone Iterables iteriert. Diese Anweisung kann nur in Kontexten verwendet werden, in denen await
verwendet werden kann, was den Körper einer asynchronen Funktion und ein Modul einschließt.
Probieren Sie es aus
async function* foo() {
yield 1;
yield 2;
}
(async () => {
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
-
Empfängt bei jeder Iteration einen Wert aus der Sequenz. Kann 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 wurden, sind nicht lokal zur Schleife, d.h. sie befinden sich im selben Geltungsbereich wie diefor await...of
Schleife. iterable
-
Ein asynchrones oder synchrones Iterable. Die Quelle der Sequenz von Werten, auf denen die Schleife operiert.
statement
-
Eine Anweisung, die bei jeder Iteration ausgeführt wird. Kann auf
variable
verweisen. Sie können einen Block verwenden, um mehrere Anweisungen auszuführen.
Beschreibung
Wenn eine for await...of
-Schleife über ein Iterable iteriert, ruft sie zunächst die [Symbol.asyncIterator]()
-Methode des Iterables auf, die einen asynchronen Iterator zurückgibt. Wenn 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 eingeschlossen wird, wobei die value
-Eigenschaft aufgelöst wird, wenn es sich ebenfalls um ein Promise handelt. Die Schleife ruft dann wiederholt die next()
-Methode des endgültigen asynchronen Iterators auf und erwartet das zurückgegebene Promise, was die Sequenz von Werten erzeugt, die der variable
zugewiesen werden.
Eine for await...of
-Schleife beendet sich, wenn der Iterator abgeschlossen ist (das erwartete next()
-Ergebnis ist ein Objekt mit done: true
). Wie bei anderen Schleifenanweisungen können Sie innerhalb von statement
Kontrollflussanweisungen verwenden:
break
beendet die Ausführung vonstatement
und geht zur ersten Anweisung nach der Schleife.continue
beendet die Ausführung vonstatement
und geht zur nächsten Iteration der Schleife.
Wenn die for await...of
-Schleife vorzeitig beendet wurde (z. B. durch eine break
-Anweisung oder wenn ein Fehler auftritt), wird die return()
-Methode des Iterators aufgerufen, um eventuelle Aufräumarbeiten durchzuführen. Das zurückgegebene Promise wird erwartet, bevor die Schleife beendet wird.
for await...of
funktioniert im Allgemeinen genauso wie die for...of
-Schleife und teilt viele der gleichen Syntaxen und Semantiken. Es gibt einige Unterschiede:
for await...of
funktioniert sowohl mit synchronen als auch asynchronen Iterables, währendfor...of
nur mit synchronen Iterables funktioniert.for await...of
kann nur in Kontexten verwendet werden, in denenawait
verwendet werden kann, was den Körper einer asynchronen Funktion und ein Modul einschließt. Auch wenn das Iterable synchron ist, wartet die Schleife trotzdem den Rückgabewert für jede Iteration, was aufgrund des wiederholten Promise-Auseinandersetzens langsamer ist.- Wenn das
iterable
ein synchrones Iterable ist, das Promises liefert, würdefor await...of
eine Sequenz von aufgelösten Werten erzeugen, währendfor...of
eine Sequenz von Promises erzeugen würde. (Seien Sie jedoch vorsichtig bei der Fehlerbehandlung und Aufräumarbeit — siehe Iterieren über synchrone Iterables und Generatoren) - Für
for await...of
kann dievariable
der Bezeichnerasync
sein (z. B.for await (async of foo)
);for...of
verbietet diesen Fall.
Wie for...of
, wenn Sie eine using
-Deklaration verwenden, dann darf die Variable nicht of
genannt werden:
for await (using of of []); // SyntaxError
Dies soll eine Syntaxzweideutigkeit mit dem gültigen Code for await (using of [])
vermeiden, bevor using
eingeführt wurde.
Beispiele
Iterieren über asynchrone Iterables
Sie können auch über ein Objekt iterieren, das explizit das asynchrone Iterable-Protokoll 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
Iterieren über asynchrone Generatoren
Da die Rückgabewerte asynchroner Generatorfunktionen dem asynchronen Iterable-Protokoll 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 zur Iteration über einen asynchronen Generator mit for await...of
, betrachten Sie die Iteration über Daten von einer API.
Dieses Beispiel erstellt zunächst ein asynchrones Iterable für einen Datenstrom und nutzt 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");
Iterieren über synchrone Iterables und Generatoren
Die for await...of
-Schleife konsumiert auch synchrone Iterables und Generatoren. In diesem Fall erwartet sie intern ausgegebene Werte, bevor sie sie der Schleifensteuerungsvariable 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:
Seien Sie sich bewusst, dass die Erzeugung von abgelehnten Promises aus einem synchronen Generator bei der Verwendung von for await...of
einen Fehler werfen kann 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(new Error("failed"));
yield 4;
throw new Error("throws");
} 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 Error: failed
// 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> Error: failed }
// 4
// caught Error: throws
// called finally
Um sicherzustellen, dass 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 die ausgegebenen Promises explizit innerhalb der Schleife.
(async () => {
try {
for (const numOrPromise of generatorWithRejectedPromises()) {
console.log(await numOrPromise);
}
} catch (e) {
console.log("caught", e);
}
})();
// 0
// 1
// 2
// caught Error: failed
// called finally
Spezifikationen
Specification |
---|
ECMAScript® 2026 Language Specification # sec-for-in-and-for-of-statements |