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 erstellt eine Schleife, die über asynchrone iterierbare Objekte sowie synchronisierte Iterables iteriert. Diese Anweisung kann nur in Kontexten verwendet werden, in denen auch await verwendet werden kann, wozu der Rumpf einer async function und ein Modul gehören.

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

js
for await (variable of iterable)
  statement
variable

Empfängt bei jeder Iteration einen Wert aus der Sequenz. Kann entweder eine Deklaration mit const, let oder var oder ein Zuweisungsziel sein (z.B. eine vorher deklarierte Variable, eine Objekteigenschaft oder ein Destrukturierungsmuster). Mit var deklarierte Variablen sind nicht lokal zur Schleife, d.h. sie befinden sich im gleichen Gültigkeitsbereich, in dem sich die for await...of-Schleife befindet.

iterable

Ein asynchrones oder synchrones Iterable. Die Quelle der Wertesequenz, auf die die Schleife operiert.

statement

Ein 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, ruft sie zunächst die [Symbol.asyncIterator]()](/de/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator)-Methode des Iterables auf, welche einen asynchronen Iterator zurückgibt. Existiert die Methode @asyncIterator nicht, wird eine [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 Methoden next(), return() und throw() zurückgegebene Objekt in ein aufgelöstes oder abgelehntes Versprechen gewrappt wird, wobei die value-Eigenschaft aufgelöst wird, falls es sich auch um ein Versprechen handelt. Die Schleife ruft dann wiederholt die next()-Methode des finalen asynchronen Iterators auf und wartet auf das zurückgegebene Versprechen, um die Wertesequenz zu erzeugen, die der variable zugewiesen wird.

Eine for await...of-Schleife wird beendet, 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 stoppt die statement-Ausführung und geht zur ersten Anweisung nach der Schleife.
  • continue stoppt die statement-Ausführung und geht zur nächsten Iteration der Schleife.

Wenn die for await...of-Schleife vorzeitig beendet wurde (z.B. durch eine break-Anweisung oder einen Fehler), wird die return()-Methode des Iterators aufgerufen, um Aufräumarbeiten durchzuführen. Das zurückgegebene Versprechen wird erwartet, bevor die Schleife beendet wird.

for await...of funktioniert allgemein ähnlich wie die for...of-Schleife und teilt viele der gleichen Syntax und Semantik. Es gibt einige Unterschiede:

  • for await...of funktioniert sowohl bei synchronen als auch bei asynchronen Iterables, während for...of nur bei synchronen Iterables funktioniert.
  • for await...of kann nur in Kontexten verwendet werden, in denen await verwendet werden kann, darunter der Rumpf einer async function und ein Modul. Selbst wenn das Iterable synchron ist, wartet die Schleife immer noch den Rückgabewert bei jeder Iteration ab, was zu einer langsameren Ausführung aufgrund wiederholter Versprechensentpackung führt.
  • Wenn das iterable ein synchrones Iterable ist, das Versprechen liefert, würde for await...of eine Sequenz von aufgelösten Werten erzeugen, während for...of eine Sequenz von Versprechungen erzeugen würde. (Seien Sie jedoch vorsichtig mit Fehlerbehandlung und Aufräumarbeiten — siehe Iterating over sync iterables and generators)
  • Bei for await...of kann die variable der Bezeichner async sein (z.B. for await (async of foo)); for...of verbietet diesen Fall.

Beispiele

Iterieren über asynchrone Iterables

Sie können auch über ein Objekt iterieren, das explizit das asynchrone Iterable-Protokoll implementiert:

js
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 von asynchronen Generatorfunktionen dem asynchronen Iterable-Protokoll entsprechen, können sie mit for await...of durchlaufen werden.

js
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 für das Iterieren ü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 verwendet es dann, um die Größe der Antwort von der API zu bestimmen.

js
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 synchronisierte Iterables und Generatoren

Die for await...of-Schleife verarbeitet auch synchronisierte Iterables und Generatoren. In diesem Fall wartet sie intern auf die ausgegebenen Werte, bevor sie diese der Schleifensteuerungsvariable zuweist.

js
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 beim Ausgeben von abgelehnten Versprechungen aus einem synchronen Generator for await...of beim Verarbeiten des abgelehnten Versprechens einen Fehler auslöst und KEINE finally-Blöcke innerhalb dieses Generators aufruft. Dies kann unerwünscht sein, wenn Sie einige zugewiesene Ressourcen mit try/finally freigeben müssen.

js
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 geeignete Form der Schleife — for await...of für den asynchronen Generator und for...of für den synchronen — und warten Sie explizit auf ausgegebene Versprechungen innerhalb der Schleife.

js
(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

Browser-Kompatibilität

Siehe auch