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');
});
          

Facebook regenerator

Generators are available in:

  • Node >= 0.11.3 with --harmony
  • Chrome since June 2013, considered done now
  • Firefox 26

Reading material