JavaScript Generators

Pause and Resume Functions With `yield`

JavaScript Generators

Generator functions (`function*`) produce iterators automatically. `yield` pauses execution and hands a value out.

5 min read Level 3/5 #generators#yield#function*
What you'll learn
  • Write generator functions with `function*` and `yield`
  • Use generators to build lazy sequences
  • Delegate with `yield*`

A generator function (function*) is a function that you can pause. Each yield hands a value out to the caller; the function freezes until you ask for the next value. The function itself returns an iterator, so you can for..of it or [...spread] it directly.

The Bare Minimum

A 3-step generator script.js
function* counter() {
  yield 1;
  yield 2;
  yield 3;
}

const it = counter();
console.log(it.next()); // { value: 1, done: false }
console.log(it.next()); // { value: 2, done: false }
console.log(it.next()); // { value: 3, done: false }
console.log(it.next()); // { value: undefined, done: true }
▶ Preview: console

That’s the same { value, done } shape we saw with hand-written iterators — but function* builds the whole machinery for you.

Loop and Spread

A generator’s result is iterable, so all the iterable tools work.

Use a generator like any iterable script.js
function* counter() { yield 1; yield 2; yield 3; }

for (const n of counter()) console.log(n);  // 1 2 3
console.log([...counter()]);                 // [1, 2, 3]
console.log(Array.from(counter()));          // [1, 2, 3]
▶ Preview: console

Lazy Infinite Sequences

A generator only computes values on demand, so you can model infinite streams without blowing memory.

Infinite naturals — pull what you need script.js
function* naturals() {
  let n = 1;
  while (true) yield n++;
}

const it = naturals();
console.log(it.next().value);  // 1
console.log(it.next().value);  // 2
console.log(it.next().value);  // 3
▶ Preview: console

Range, Without the Boilerplate

Compare with the hand-written range from the iterators lesson.

Range with a generator script.js
function* range(start, end) {
  for (let i = start; i < end; i++) yield i;
}

console.log([...range(1, 5)]);  // [1, 2, 3, 4]
▶ Preview: console

Delegating With yield*

yield* forwards every value from another iterable.

yield* hands over to another generator script.js
function* head() { yield 1; yield 2; }
function* tail() { yield 3; yield 4; }

function* all() {
  yield* head();
  yield* tail();
}

console.log([...all()]);  // [1, 2, 3, 4]
▶ Preview: console

yield* can also delegate to any iterable (arrays, strings, sets).

Receiving Values With next(value)

The argument you pass to .next(value) becomes the result of the paused yield expression — generators are two-way.

Two-way: send a value back in script.js
function* convo() {
  const name = yield "What's your name?";
  yield `Hello, ${name}!`;
}

const it = convo();
console.log(it.next().value);          // "What's your name?"
console.log(it.next("Ada").value);     // "Hello, Ada!"
▶ Preview: console

This is rarely used in app code but is the foundation of coroutines and the implementation of async/await.

Up Next

Generators that yield promises model async streams — values that arrive over time.

JavaScript Async Iterators →