Pull to refresh

Генераторы в node.js (новый способ борьбы с лапшой)

Генераторы являются частью нововведений javascript 1.7 и давно поддерживаются в firefox. О генераторах можно почитать тут, тут и тут.
Сравнительно недавно была добавлена поддержка генераторов в V8, а следовательно и в chrome canary, а также в node.js 0.11, при этом node.js необходимо запускать либо с ключом --harmony, либо c --harmony-generators.

Существует множество способов для борьбы с колбеками в node.js, такие как файберы, вариации с event emitter. Наибольшую популярность получили промисы, на мой взгляд, благодаря наиболее понятным и прозрачным механизмам, заложенным в них. Однако, генераторы предоставляют еще более элегантные способы организации когда. И вот пример:
var fs = require('fs');

function thread(fn) {
  var gen = fn();
  function next(err, res) {
    var ret = gen.next(res);
    if (ret.done) return;
    ret.value(next);
  }  
  next();
}

thread(function *(){
  var a = yield read('Readme.md');
  var b = yield read('package.json');
  console.log(a);
  console.log(b);
});

function read(path) {
  return function(done){
    fs.readFile(path, 'utf8', done);
  }
}

Интересно? Не безызвестный TJ Holowaychuk написал библиотечку Co, которая позволяет делать вещи вроде таких:
co(function *(){
  var str = yield read(‘Readme.md’);
  str = str.replace(‘Something’, ‘Else’);
  yield write(‘Readme.md’, str);
});

Теперь обработка исключений в асинхронных вызовах станет надежнее.
co(function *(){
  try {
    var str = yield read(‘Readme.md’);
  } catch (err) {
    // whatever
  }
  str = str.replace(‘Something’, ‘Else’);
  yield write(‘Readme.md’, str);
});

Подробее в записи https://medium.com/code-adventures/174f1fe66127
Оффтоп: полученный код на node.js имеет много общего с кодом на tornado и это хоршо.
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.