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.

We'd love to hear more about your role and the company you work for
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

js
for await (variable of iterable)
  statement
variable

Erhält bei jeder Iteration einen Wert aus der Sequenz. Kann entweder eine Deklaration mit const, let oder var sein oder ein Zuweisungsziel (z.B. eine zuvor deklarierte Variable, eine Objekteigenschaft oder ein Destrukturierungsmuster). Variablen, die mit var deklariert sind, sind nicht lokal zur Schleife, d.h. sie befinden sich im gleichen Gültigkeitsbereich wie die for 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 von statement und geht zur ersten Anweisung nach der Schleife.
  • continue stoppt die Ausführung von statement 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ährend for...of nur mit synchronen Iterables arbeitet.
  • for await...of 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. 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ürde for await...of eine Folge von aufgelösten Werten erzeugen, während for...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 kann variable der Bezeichner async 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:

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

Über asynchrone Generatoren iterieren

Da die Rückgabewerte von asynchronen Generatorfunktionen dem asynchronen Iterierprotokoll 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 ü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.

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");

Ü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.

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: 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.

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

js
(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 GitHub
desktopmobileserver
Chrome
Edge
Firefox
Opera
Safari
Chrome Android
Firefox for Android
Opera Android
Safari on iOS
Samsung Internet
WebView Android
WebView on iOS
Deno
Node.js
for await...of

Legend

Tip: you can click/tap on a cell for more information.

Full support
Full support

Siehe auch