Movatterモバイル変換


[0]ホーム

URL:


MDN Web Docs

for await...of

BaselineWidely available

Thefor await...of statement creates a loop iterating overasync iterable objects as well assync iterables. This statement can only be used in contexts whereawait can be used, which includes inside anasync function body and in amodule.

Try it

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

Receives a value from the sequence on each iteration. May be either a declaration withconst,let, orvar, or anassignment target (e.g., a previously declared variable, an object property, or adestructuring pattern). Variables declared withvar are not local to the loop, i.e., they are in the same scope thefor await...of loop is in.

iterable

An async iterable or sync iterable. The source of the sequence of values on which the loop operates.

statement

A statement to be executed on every iteration. May referencevariable. You can use ablock statement to execute multiple statements.

Description

When afor await...of loop iterates over an iterable, it first gets the iterable's[Symbol.asyncIterator]() method and calls it, which returns anasync iterator. If the@asyncIterator method does not exist, it then looks for an[Symbol.iterator]() method, which returns async iterator. The sync iterator returned is then wrapped into an async iterator by wrapping every object returned from thenext(),return(), andthrow() methods into a resolved or rejected promise, with thevalue property resolved if it's also a promise. The loop then repeatedly calls the final async iterator'snext() method andawaits the returned promise, producing the sequence of values to be assigned tovariable.

Afor await...of loop exits when the iterator has completed (the awaitednext() result is an object withdone: true). Like other looping statements, you can usecontrol flow statements insidestatement:

  • break stopsstatement execution and goes to the first statement after the loop.
  • continue stopsstatement execution and goes to the next iteration of the loop.

If thefor await...of loop exited early (e.g., abreak statement is encountered or an error is thrown), thereturn() method of the iterator is called to perform any cleanup. The returned promise is awaited before the loop exits.

for await...of generally functions the same as thefor...of loop and shares many of the same syntax and semantics. There are a few differences:

  • for await...of works on both sync and async iterables, whilefor...of only works on sync iterables.
  • for await...of can only be used in contexts whereawait can be used, which includes inside anasync function body and in amodule. Even when the iterable is sync, the loop still awaits the return value for every iteration, leading to slower execution due to repeated promise unwrapping.
  • If theiterable is a sync iterable that yields promises,for await...of would produce a sequence of resolved values, whilefor...of would produce a sequence of promises. (However, beware of error handling and cleanup — seeIterating over sync iterables and generators)
  • Forfor await...of, thevariable can be the identifierasync (e.g.,for await (async of foo));for...of forbids this case.

Examples

Iterating over async iterables

You can also iterate over an object that explicitly implements async iterable protocol:

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

Iterating over async generators

Since the return values of async generator functions conform to the async iterable protocol,they can be looped usingfor await...of.

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

For a more concrete example of iterating over an async generator usingfor await...of, consider iterating over data from an API.

This example first creates an async iterable for a stream of data, then uses it to find the size of the response from the API.

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

Iterating over sync iterables and generators

for await...of loop also consumes sync iterables and generators. In that case it internally awaits emitted values before assign them to the loop control variable.

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

Note:Be aware of yielding rejected promises from a sync generator. In such case,for await...of throws when consuming the rejected promise and DOESN'T CALLfinally blocks within that generator. This can be undesirable if you need to free some allocated resources withtry/finally.

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

To makefinally blocks of a sync generator always called, use the appropriate form of the loop —for await...of for the async generator andfor...of for the sync one — and await yielded promises explicitly inside the loop.

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

Specifications

Specification
ECMAScript® 2026 Language Specification
# sec-for-in-and-for-of-statements

Browser compatibility

See also

Help improve MDN

Learn how to contribute.

This page was last modified on byMDN contributors.


[8]ページ先頭

©2009-2025 Movatter.jp