14. What are async iterators and generators in JavaScript?
hard

Async iterators and generators are two new features introduced in JavaScript with ES6. They provide a way to generate asynchronous data streams, which can help improve the performance of applications that rely on repeated requests to external APIs or databases.


An async iterator is an object that provides a [Symbol.async]() method that returns an iterator function. This iterator function allows you to iterate over asynchronous data in a way that is similar to how you would iterate over synchronous data using regular iterators. The await keyword can be used inside an async iterator function to pause the execution of the code until a promise has resolved or rejected.

const myAsyncIterator = async function* () {
  const data = await fetch('https://api.example.com/data');
  while (true) {
    const item = await data;
    yield item;
  }
};

myAsyncIterator();

In this example, we're creating an async iterator that fetches data from an API and yields each item as it becomes available. We can use the await keyword to pause the execution of the code until the promise returned by the fetch() function has resolved.

A generator is similar to an async iterator in that it provides a way to generate a sequence of values, but it does so synchronously. Generators are defined using the function* syntax and allow you to use the yield keyword inside the function to pause its execution and return a value.

function* myGenerator() {
  let i = 0;
  while (true) {
    yield i++;
  }
}

const iterator = myGenerator();
console.log(iterator.next()); // { value: 0, done: false }
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }

In this example, we're defining a generator that generates a sequence of numbers starting from 0. We can use the next() method to iterate over the values generated by the generator.