Generators
Generators¶
Also called function *
, generators allow you to create functions whose execution can be paused and then later resumed maintaining the state between pause-resume transitions. The value returned from a generator is called an iterator
and can be used to control this pause-resume
transition.
Here is a simple example of a generator function that generates an infinite list of whole numbers.
function* wholeNumbers() {
var current = 0;
while(true) {
yield current++;
}
}
The yield
contextual keyword is used to return control from a generator (effectively pausing function execution) along with an optional value (here current
). You can get access to this value using the iterator
's .next()
member function, this is shown below:
function* wholeNumbers() {
var current = 0;
while(true) {
yield current++;
}
}
var iterator = wholeNumbers();
console.log(iterator.next()); // 0
console.log(iterator.next()); // 1
console.log(iterator.next()); // 2
// so on till infinity....
Now that you have seen function*
, yield
and .next()
we can dig deeper.
Catching Errors¶
Any errors thrown (intentially using throw
or unintentionally due to error) from the generator can be caught using try/catch
just like normal function executions. This is demonstrated below:
function* wholeNumbers() {
var current = 0;
while(true) {
if (current === 3)
throw new Error('3 is the magic number');
else
yield current++;
}
}
var iterator = wholeNumbers();
console.log(iterator.next()); // 0
console.log(iterator.next()); // 1
console.log(iterator.next()); // 2
try {
console.log(iterator.next()); // Will throw an error
}
catch(ex) {
console.log(ex.message); // 3 is the magic number
}
Controlling function execution externally¶
The iterator returned from the generator function can be used to control the state inside the generator function as well.
// TODO: example