Generators and Iteration

A Generator is a special type of function that can be paused and resumed, allowing for the creation of memory-efficient iterators and complex asynchronous flows. Unlike a regular function that runs to completion, a generator "Yields" values one at a time.


1. Syntax: The function* and yield

Generators are defined using the function* syntax and use the yield keyword to return a value and suspend execution.

function* numberSequence() {
    yield 1;
    yield 2;
    yield 3;
}

const gen = numberSequence(); // Returns a Generator Object
console.log(gen.next().value); // 1

2. The Iteration Protocol

A generator object is both an Iterable and an Iterator.


3. Communication: Passing values back

Generators are two-way streets. Not only can they yield values to the caller, but the caller can also send values Back into the generator through the next(value) method.

function* conversationalist() {
    const name = yield "What is your name?";
    console.log(`Hello, ${name}`);
}

const gen = conversationalist();
gen.next(); // Starts the generator
gen.next("Alice"); // Sends "Alice" into the variable 'name'

4. Asynchronous Generators

Modern JavaScript supports async function*, which allows you to yield promises. This is commonly used for processing streams of data or results from paginated APIs.

async function* fetchPages(url) {
    while (url) {
        const response = await fetch(url);
        const data = await response.json();
        yield data.items;
        url = data.nextPage;
    }
}

Interview Pro-Tips: Generators vs. Async/Await

If an interviewer asks about the relationship between them:


Technical Summary

  1. Suspension: Local context (variables, pointer) is preserved between yields.
  2. Lazy Evaluation: Processing items only when consumed.
  3. Stream Processing: Ideal for handling datasets too large to fit in a single array.