Pause and Resume Functions With `yield`
JavaScript Generators
Generator functions (`function*`) produce iterators automatically. `yield` pauses execution and hands a value out.
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
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 } 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.
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] Lazy Infinite Sequences
A generator only computes values on demand, so you can model infinite streams without blowing memory.
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 Range, Without the Boilerplate
Compare with the hand-written range from the iterators lesson.
function* range(start, end) {
for (let i = start; i < end; i++) yield i;
}
console.log([...range(1, 5)]); // [1, 2, 3, 4] Delegating With yield*
yield* forwards every value from another iterable.
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] 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.
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!" 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.