CodeBlanks Logo Icon CodeBlanks

Asynchronous iteration

JavaScript course · Advanced · Lesson 75/100

Learn to traverse async iterables with for await...of.

What is an async iterable?

An async iterable is an object with a Symbol.asyncIterator method. The method returns an async iterator whose .next() returns a Promise. The for await...of loop consumes this structure step by step.

const stream = {
  [Symbol.asyncIterator]() {
    return this;
  },
  async next() {
    return { value: 1, done: false };
  }
};

This pattern fits data that arrives over time: paginated APIs, log streams and similar flows.

The pagination pattern

Async iterables are ideal for walking paginated APIs. Without knowing the total page count up front, each next() call fetches the next page via await. When the last page is reached, you return done: true.

async next() {
  if (this.page >= this.total) {
    return { done: true };
  }
  this.page = this.page + 1;
  const data = await fetchPage(this.page);
  return { value: data, done: false };
}

This approach processes the stream piece by piece and keeps memory use low.

Exercise Paginated data stream

Create an async iterable object named pages. Give it current: 0 and total: 3 properties. The Symbol.asyncIterator method should return this. Write an async next() method: when current reaches total, return { done: true }; otherwise increment current by 1, await Promise.resolve('page-' + current) for the value, and return { value, done: false }. Finally, iterate pages with for await...of and log each value with console.log.

Show example solution
const pages = {
  current: 0,
  total: 3,
  [Symbol.asyncIterator]() {
    return this;
  },
  async next() {
    if (this.current >= this.total) {
      return { value: undefined, done: true };
    }
    this.current = this.current + 1;
    const value = await Promise.resolve('page-' + this.current);
    return { value, done: false };
  }
};
for await (const page of pages) {
  console.log(page);
}

Test yourself

  1. Match async iteration concepts

    Symbol.asyncIterator
    protocol key
    .next()
    returns a Promise
    for await...of
    consumes
    { value, done }
    result shape
  2. Which syntax consumes an async iterable?

    • for (const x of asyncIterable)
    • asyncIterable.forEach(await ...)
    • while (await asyncIterable.next())
    • for await (const x of asyncIterable)
    Show answer

    for await (const x of asyncIterable) — Correct! for await...of is the standard syntax for consuming async iterables.

  3. The async iterator method

    const stream = {
      [Symbol.____]() { return this; },
      async next() {
        return { value: 1, done: true };
      }
    };
    Show answer
    const stream = {
      [Symbol.asyncIterator]() { return this; },
      async next() {
        return { value: 1, done: true };
      }
    };

All lessons in Advanced