Yield in generators
1. What yield does
yieldis an operator that returns a value from a generator function to the outside and pauses execution until the next call to.next().
That is:
- when the generator "reaches"
yield, it freezes; - when we call
.next()again, it resumes right after theyieldwhere it stopped.
2. The simplest example
function* gen() {
console.log('Before the first yield');
yield 1;
console.log('Between yields');
yield 2;
console.log('After the second yield');
}
const it = gen();
console.log(it.next()); // { value: 1, done: false }
console.log(it.next()); // { value: 2, done: false }
console.log(it.next()); // { value: undefined, done: true }What happens step by step:
gen()returns an iterator object -> the function has not started yet.it.next()-> starts the function -> reachesyield 1, returns{ value: 1 }and freezes.- The next
it.next()-> continues from the same place, afteryield 1. - After the second
yieldit "freezes" again. - When
done: true, the generator has finished.
3. How yield returns a value
function* seq() {
yield 'A';
yield 'B';
yield 'C';
}
const it = seq();
console.log(it.next().value); // "A"
console.log(it.next().value); // "B"
console.log(it.next().value); // "C"
console.log(it.next().done); // trueyield is a "temporary return":
it returns a value but does not finish the function.
4. Passing a value back into the generator via next(value)
yield not only returns data to the outside,
it can also receive a value back on the next call to .next(value).
function* dialog() {
const name = yield 'What is your name?';
yield `Hello, ${name}!`;
}
const chat = dialog();
console.log(chat.next().value); // "What is your name?"
console.log(chat.next('Tim').value); // "Hello, Tim!"- The first
next()started the generator and reached the firstyield. - The second
next('Tim')passed'Tim'into the generator, and that value ended up inconst name.
5. Finishing the generator via return
When the generator reaches the end,
or if you call iterator.return(value),
it finishes execution with done: true.
function* numbers() {
yield 1;
yield 2;
}
const it = numbers();
console.log(it.next()); // { value: 1, done: false }
console.log(it.return('stop')); // { value: 'stop', done: true }
console.log(it.next()); // { value: undefined, done: true }6. yield* - delegating to another generator
Sometimes one generator can "hand over control" to another via yield*.
function* inner() {
yield 'B';
yield 'C';
}
function* outer() {
yield 'A';
yield* inner(); // hands control over to another generator
yield 'D';
}
for (const val of outer()) {
console.log(val);
}Output:
A
B
C
Dyield* is a nested loop: "just yield all the values of another generator".
7. Important point - "laziness"
yield makes generators lazy -
values are computed only on demand, not in advance.
function* range(start, end) {
for (let i = start; i <= end; i++) {
console.log('Generating', i);
yield i;
}
}
for (const num of range(1, 3)) {
console.log('Received:', num);
}Output:
Generating 1
Received: 1
Generating 2
Received: 2
Generating 3
Received: 3The generator "creates" values as needed, instead of storing the whole range at once.
8. Errors inside a generator (throw)
You can "throw" an error right inside the generator:
function* gen() {
try {
yield 1;
} catch (e) {
console.log('Error caught:', e.message);
}
}
const it = gen();
it.next();
it.throw(new Error('Something is wrong')); // Error caught: Something is wrongSummary
| Feature | Description |
|---|---|
| What it does | Pauses execution and returns a value |
| Resuming | Via .next() |
| Can pass values back | Yes (next(value)) |
| Can be finished | Via return() |
| Can be delegated | Via yield* |
| Evaluation | Lazy |
| Works only in | function* (generators) |
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.