Chapter 12: Generators, advanced iteration
12.1 Generators
Generators can return (“yield”) multiple values, one after another, on-demand.
function* generateSequence() {
yield 1;
yield 2;
return 3;
}
When the next()
is called, it runs the execution until the nearest yield <value>
statement.
The result (object):
value
: the yielded value.done
:true
if the function code has finished, otherwisefalse
.
let generator = generateSequence();
let one = generator.next();
Generators are iterable
We can loop over the generator using for..of
. However, it ignores the last value, when done: true
.
To fix that, we must return them with yield
.
function* generateSequence() {
yield 1;
yield 2;
yield 3;
}
Using generators for iterables
let range = {
from: 1,
to: 5,
*[Symbol.iterator]() { // a shorthand for [Symbol.iterator]: function*()
for(let value = this.from; value <= this.to; value++) {
yield value;
}
}
};
Generators may generate values forever.
Generator composition
There’s a special yield*
syntax to “embed” (compose) one generator into another.
function* generatePasswordCodes() {
// 0..9
yield* generateSequence(48, 57);
“yield” is a two-way street
yield
not only returns the result to the outside, but also can pass the value inside the generator.
function* gen() {
// Pass a question to the outer code and wait for an answer
let result = yield "2 + 2 = ?"; // (*)
alert(result);
}
let generator = gen();
let question = generator.next().value; // <-- yield returns the value
generator.next(4);
generator.throw
let question = generator.next().value;
generator.throw(new Error("The answer is not found in my database"));
12.2 Async iterators and generators
Async iterators
Use
Symbol.asyncIterator
next()
should return a promiseUse
for await (let item of iterable)
loop to iterate over the objectThe spread syntax
...
doesn’t work asynchronously.
Async generators
async function* generateSequence(start, end) {
for (let i = start; i <= end; i++) {
// yay, can use await!
await new Promise(resolve => setTimeout(resolve, 1000));
yield i;
}
}
result = await generateSequence.next();
Last updated