Start · Sprachen · JavaScript · Referenz · for await...of

for await...of

Anweisung

Erstellt eine Schleife, die über <code>async</code>-iterierbare sowie synchrone iterierbare Objekte iteriert und dabei jeden Wert mit <code>await</code> auflöst.

seit JavaScript ES2018 Kategorie: syntax

Signatur

for await (variable of iterable) { statement }

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

Typ
void
Beschreibung
Die Anweisung gibt keinen Wert zurück. Sie steuert den Ablauf einer 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();
5 4 3 2 1 0 Fertig!

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');
Zeile 1: Hallo Welt Zeile 2: JavaScript ist toll Insgesamt 2 Zeilen gelesen.

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();
[1] sunt aut facere repellat provident ... [2] qui est esse [3] ea molestias quasi exercitationem ...

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);
}
1 2 3 4

// 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 break oder return verlassen, ruft die Laufzeit automatisch die return()-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...catch um die Schleife abfangen.