Generator syntax
function *numnums() {
yield 1;
yield 2;
yield 3;
}
var iter = numnums(); // invoke the generator to return an iterable
Iterable interface
function *foo() {
var x = yield 1;
console.log(x);
}
var iter = foo();
iter.next();
iter.next(5);
iter.throw('oops');
for..of loops
for(var i of [4,5,6]) {
console.log(i); // 4 5 6
}
Returns values vs. for..in which returns keys
Works with any iterables
Generators with for..of loops
function *ham() {
yield 'delicious';
yield 'tasty';
return 'moist';
}
for(var taste of ham()) {
console.log(taste); // delicious tasty
}
return statement is ignored in for..of loops
Infinite generator
function *toInfinityAndBeyond() {
var i = 0;
while (true) {
yield i++;
}
}
for(var i of toInfinityAndBeyond()) {
console.log(i);
if (i >= 10) { break; }
}
Passing messages to the generator
function *bar() {
var x = yield 1;
var y = yield 2;
return x + y;
}
var b = bar();
console.log(b.next()) // { value: 1 }
console.log(b.next(14)) // { value: 2 } pass 14 and set to x
console.log(b.next(16)) // { value: 30, done: true } pass 16 and set to y
Yielding to another generator
function *a() {
yield 1;
yield 2;
return 3;
}
function *b() {
yield 0;
var x = yield* a();
console.log(x);
}
for (var i of b()) {
console.log(i)
}
iterator.throw()
function *foo() { }
var iter = foo();
try {
iter.throw( "Oops!" );
}
catch (err) {
console.log( "Error: " + err ); // Error: Oops!
}
Generators and flow control with Q
var Q = require('q');
var fs = require('fs');
var stat = Q.denodeify(fs.stat);
Q.spawn(function *(){
var stat1 = yield stat('index.html');
var stat2 = yield stat('notes.md');
console.log(stat1.size, stat2.size);
});
var Q = require('q'), fs = require('fs');
var immaThrowAnError = function() {
return {then: function(){throw new Error('ham'); }};
};
Q.spawn(function *(){
try {
yield immaThrowAnError();
} catch(e) {
console.log('caught the error');
}
console.log('finished');
});
Generators are available in:
Node >= 0.11.3 with --harmonyReading material