ES6+advanced
Generator Functions
Functions that can pause and resume execution using yield, producing values lazily one at a time and automatically implementing the iterator protocol.
A generator can pause mid-execution and resume later. yield is where it stops.
A generator function is like a bookmark in a very long book: instead of reading the whole book in one sitting, you read one chapter, hand it over, and put in a bookmark — the book remembers exactly where you stopped.
Key Concepts
1
function* count() {
yield 1;
yield 2;
yield 3;
}2
const g = count();
g.next(); // { value: 1, done: false }
g.next(); // { value: 2, done: false }
g.next(); // { value: 3, done: false }
g.next(); // { value: undefined, done: true }3
Calling it runs nothing. It returns a generator object. The body executes only when next() is called,
and pauses again at the next yield.
next()yield
4
Which gives laziness for free.
function* naturals() { let n = 0; while (true) yield n++; }5
An infinite loop that does not hang, because it only advances when asked.
6
And it implements the iterator protocol, so a generator works with for...of, spread and destructuring
with no extra code.
for...of
7
Two-way communication is the part people miss. next(value) sends a value in, and it becomes the
result of the paused yield:
next(value)yield
8
function* dialogue() {
const name = yield 'What is your name?';
const age = yield `Hello ${name}, how old are you?`;
return `${name} is ${age}`;
}Hello ${name}, how old are you?${name} is ${age}
9
const d = dialogue();
d.next(); // asks for the name
d.next('Asha'); // name = 'Asha'; asks for the age
d.next(30); // returns the summary10
That is what made generators the basis for async control flow before async/await — co-routines that yield
promises, with a driver resuming them. async/await is that pattern built into the language.
async/await
11
*yield delegates to another iterable.**
function* inner() { yield 1; yield 2; }
function* outer() { yield 0; yield* inner(); yield 3; }
[...outer()]; // [0, 1, 2, 3]yield*
12
throw and return control it from outside.
g.return(99); // ends it; finally blocks run
g.throw(err); // raises inside, at the yield pointthrowreturn
13
Where they are genuinely useful today. Traversing a tree lazily, paginated APIs as a flat sequence,
generating ids, and state machines. Redux-Saga is built entirely on them.
14
And where not. Ordinary asynchronous code — that is async/await, which is more familiar and reads
better.
async/await
15
What the interviewer is probing.1. "What does yield do?" Probing: the mechanism. Stalls: "Returns a value." Moves up: it
suspends the function and returns a value, keeping the local state so the next call resumes where it
left off.
16
2. "How do you send a value into a generator?" Probing: two-way communication. Stalls: "You
cannot." Moves up: next(value) — the argument becomes the result of the paused yield expression.
17
3. "Where are generators genuinely useful?" Probing: practical use. Stalls: "Rarely." *Moves
up:* lazy and infinite sequences, custom iterables, and controlled stepping through work — plus they
underpin how async/await was originally implemented.
18
*4. "What does yield do?"* Probing: delegation. Stalls: "Yields an array." Moves up:* it
delegates to another iterable, flattening its values into this generator's sequence.