Signatur
Beschreibung
for await...of ist die asynchrone Variante der for...of-Schleife. Sie iteriert über asynchron iterierbare Objekte (d. h. Objekte, die die Methode [Symbol.asyncIterator]() implementieren) sowie reguläre synchrone Iterables (wie Array, Map, Set oder String). Bei jedem Schleifendurchlauf wird das Promise, das der Iterator liefert, automatisch mit await aufgelöst, bevor der Schleifenrumpf ausgeführt wird.
for await...of darf ausschließlich innerhalb von async-Funktionen oder auf der Top-Level eines ES-Moduls (Top-Level await) verwendet werden. Typische Einsatzbereiche sind das Verarbeiten von Async Generators, das zeilenweise Einlesen von Node.js-Streams, das sequenzielle Auflösen von API-Antworten oder das Iterieren über ReadableStream-Objekte der Fetch-API.
Neben eigenen asynchronen Iteratoren eignet sich die Schleife besonders für:
- Node.js-
Readable-Streams (implementieren[Symbol.asyncIterator]ab Node.js 10) - Async-Generator-Funktionen (
async function*) - Arrays oder andere synchrone Iterables, wenn der Schleifenkörper selbst asynchrone Operationen enthält und sequenziell ablaufen soll
Anders als Promise.all() verarbeitet for await...of die Elemente sequenziell – jede Iteration wartet auf den Abschluss der vorherigen. Soll Parallelität gewünscht sein, ist Promise.all() oder Promise.allSettled() die bessere Wahl. Fehlerbehandlung erfolgt wie gewohnt mit try...catch um die gesamte Schleife.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $variable Pflicht | any | — | Eine Variable (deklariert mit const, let oder var) oder ein zuweisbares Muster (Destructuring), das in jedem Durchlauf den aufgelösten Wert des aktuellen Iterationsschritts erhält. |
| $iterable Pflicht | AsyncIterable | Iterable | AsyncGenerator | ReadableStream | — | Ein asynchron iterierbares Objekt (implementiert [Symbol.asyncIterator]) oder ein reguläres synchrones Iterable (implementiert [Symbol.iterator]). Bei synchronen Iterables werden die Werte automatisch als aufgelöste Promises behandelt. |
| $statement Pflicht | statement | — | Der Schleifenrumpf – beliebige JavaScript-Anweisungen, die für jeden aufgelösten Wert ausgeführt werden. Innerhalb des Rumpfs stehen break, continue und return zur Verfügung. |
Rückgabewert
async-Funktion und hat keinen Rückgabewert.Beispiele
Async Generator mit for await...of verarbeiten
// Async Generator, der Zahlen mit Verzögerung liefert
async function* countdown(start) {
for (let i = start; i >= 0; i--) {
await new Promise(resolve => setTimeout(resolve, 200));
yield i;
}
}
const run = async () => {
for await (const num of countdown(5)) {
console.log(num);
}
console.log('Fertig!');
};
run();
Node.js-Datei zeilenweise mit einem Stream lesen
import { createReadStream } from 'node:fs';
import { createInterface } from 'node:readline';
const processFile = async (filePath) => {
const fileStream = createReadStream(filePath, { encoding: 'utf8' });
const rl = createInterface({ input: fileStream, crlfDelay: Infinity });
let lineNumber = 0;
for await (const line of rl) {
lineNumber++;
console.log(`Zeile ${lineNumber}: ${line}`);
}
console.log(`Insgesamt ${lineNumber} Zeilen gelesen.`);
};
processFile('./beispiel.txt');
Sequenzielles Auflösen mehrerer API-Anfragen
const urls = [
'https://jsonplaceholder.typicode.com/posts/1',
'https://jsonplaceholder.typicode.com/posts/2',
'https://jsonplaceholder.typicode.com/posts/3',
];
// Async Generator erzeugt nacheinander aufgelöste Fetch-Responses
async function* fetchSequentially(urlList) {
for (const url of urlList) {
const response = await fetch(url);
if (!response.ok) throw new Error(`HTTP-Fehler: ${response.status}`);
yield response.json();
}
}
const loadPosts = async () => {
try {
for await (const post of fetchSequentially(urls)) {
console.log(`[${post.id}] ${post.title}`);
}
} catch (err) {
console.error('Fehler beim Laden:', err.message);
}
};
loadPosts();
Top-Level await in einem ES-Modul
// datei.mjs — direkt auf Modul-Top-Level ohne async-Wrapper
async function* asyncRange(from, to) {
for (let i = from; i <= to; i++) {
yield await Promise.resolve(i);
}
}
for await (const value of asyncRange(1, 4)) {
console.log(value);
}
// Wichtig · Fallstricke
Nur in async-Kontexten erlaubt: for await...of außerhalb einer async-Funktion oder eines ES-Moduls (Top-Level await) zu verwenden, führt zu einem SyntaxError.
- Sequenziell statt parallel: Jede Iteration wartet auf die vorherige. Für parallele Verarbeitung lieber
Promise.all()einsetzen. - Ressourcen-Freigabe: Wird die Schleife vorzeitig mit
breakoderreturnverlassen, ruft die Laufzeit automatisch diereturn()-Methode des Iterators auf, sofern vorhanden – das erlaubt sauberes Aufräumen (z. B. Stream schließen). - Synchrone Iterables: Werden auch unterstützt. Die Werte werden intern in
Promise.resolve()gewickelt, bevor sie übergeben werden. - Browser-Kompatibilität: Alle modernen Browser (Chrome 63+, Firefox 57+, Safari 12+, Edge 79+) sowie Node.js ab Version 10 unterstützen
for await...of. Internet Explorer wird nicht unterstützt. - Fehlerbehandlung: Ein in der Iteration geworfener Fehler (durch ein abgelehntes Promise) lässt sich mit
try...catchum die Schleife abfangen.