Generators
Normally, functions follow a run-to-completion model. When a function is invoked, it runs until it completes and then returns.
However, generators are functions that can be exited and later re-entered. Their context (variable bindings) will be saved across re-entrances.
Creating generator functions
function* generatorFunc() {
console.log("First");
yield "yield 1";
console.log("Second");
yield "yield 2";
console.log("Third");
return;
}
Invoking a generator function returns a generator object, that has many properties that we probably won`t have to use.
yield
keyword
The execution of the generator gets "paused" when it encounters a yield keyword. And the catch is that the next time we run the function, it remembered where it previously paused, and runs from there on
Invoking a generator function
The generator object contains a next
method that can be used to iterate the generator object.
However in order to remember the state of the generator, we need to store the generator object in a variable.
const genObj = generatorFunc();
genObj.next();
genObj.next();
genObj.next();
First
{value: "yield 1", done: false}
Second
{value: "yield 2", done: false}
Third
{value: undefined, done: true}
The value of the done
property is true
when the return
keyword is encountered.
The done
property is crucial because we can only iterate a generator object once., after which it will return undefined
forever.
If you want to iterate it again you have to create a new generator object.
Iterators
What make an
The generator object is an iterator, meaning we can use for of
loops and the spread
operator on it.
const genObj = generatorFunc();
[...genObj];
// [ "yield 1", "yield 2" ]