Generators functions take the following form function* name() {}
. Or our preferred const name = function* () {};
, since we avoid function declarations in favor of function expressions.
Calling a generator doesn't actually run any of its contents. A call to a generator returns a generator instance.
const foo = function* () {
console.log("foo");
}
// No console output here
// bar is now an instance of the generator and the console.log has never been run.
const bar = foo();
To use a generator instance we have to call .next()
const foo = function* () {
console.log("here");
}
// No console output here
const bar = foo();
bar.next(); //=> "here"
.next()
returns an object that looks like this:
{ value: undefined, done: true }
What do value
and done
mean?
done
means that the generator doesn't have any more code to execute. AKA we are past the last yield
statement. To understand value
, we have to look at yield
.
const foo = function* (x) {
yield x;
}
const bar = foo(3);
console.log(bar.next()); //=> {value: 3, done: false}
console.log(bar.next()); //=> {value: undefined, done: true}
A yield
statement tells the generator to stop executing and return the following value. You can have yield
statements without a return value. The generator will return done: true
on the subsequent call to next after the last yield
statement (see above).