Question 29

Question

How would you create an infinite async iterator using Symbol.asyncIterator?

Answer

class InfiniteAsyncIterator {
  constructor() {
    this[Symbol.asyncIterator] = this.asyncIterator.bind(this);
  }

  async* asyncIterator() {
    let count = 0;
    while (true) {
      yield `Value ${count++}`;
      await new Promise(resolve => setTimeout(resolve, 100)); // Simulate an async operation
    }
  }
}

const iterator = new InfiniteAsyncIterator();
async function consumeIterator() {
  for await (const value of iterator) {
    console.log(value);
    // Do something with the yielded value...
    if (count > 10) break; // Stop after a certain number of values
  }
}

consumeIterator(); 

Explanation:

  1. Symbol.asyncIterator: This special symbol ensures our class functions as an async iterator. We attach our asyncIterator method to it.

  2. async* asyncIterator():

    • Declares an asynchronous generator function using async*.

    • Uses a while (true) loop to create an infinite stream.

    • yield: Yields the current value (Value ${count}) and pauses execution.

    • await new Promise(...): Introduces a delay to simulate an asynchronous operation before yielding the next value.

  3. consumeIterator(): An example function demonstrating how to use the iterator:

    • Uses for await ... of to iterate over the values yielded by the iterator.

    • Logs each value (you'd replace this with your actual processing logic).

    • Sets a limit (count > 10) to break out of the loop after a certain number of iterations.

Key Points:

  • Infinite Loop: The while (true) loop ensures that the iterator generates values indefinitely.

  • Async Operations: Using await allows you to simulate real-world asynchronous tasks within the iterator.

  • for await ... of: The specific syntax for iterating over async iterators in JavaScript.

Remember: Infinite loops can consume resources, so use them cautiously and implement appropriate stopping mechanisms if needed (like in our example).

Last updated