ES6的generator. 方便编写顺序的异步代码.

jopen 9年前

gpipe

基于nodejs 0.11.14, ES6的generator. 方便编写顺序的异步代码.

nodejs v0.11.14

使用 generator 异步代码的例子:

var assert = require('assert'),      gpipe = require('./lib/gpipe.js');    function fA(a, callback) {      setTimeout(function () {          callback(a, 'aaa');      }, 1000);  }    function fB(b, callback) {      setTimeout(function () {          callback(b, 'bbb');      }, 1000);  }    gpipe.scc(function* (ctrl) {      var A = yield fA('a1', ctrl);      assert.strictEqual(A[0], 'a1');        assert.strictEqual(A[1], 'aaa');          var B = yield fB('b1', ctrl);      assert.strictEqual(B[0], 'b1');        assert.strictEqual(B[1], 'bbb');        var C = yield gpipe.mcc(function* (ctrl) {          yield fA('a2', ctrl('a'));          yield fB('b2', ctrl('b'));      }, ctrl);      assert.strictEqual(C[0]['a'][0], 'a2');        assert.strictEqual(C[0]['a'][1], 'aaa');        assert.strictEqual(C[0]['b'][0], 'b2');      assert.strictEqual(C[0]['b'][1], 'bbb');    });

如你所见,异步代码在形态上已经变成“同步”。

不止如此, gpipe提供两个函数:

  • scc(generator[, callback]) scc串行代码段,B的fB会等待A的fA,然后运行

  • mcc(generator[, callback]) mcc并行代码段, C中的fA,fB同时运行, fB不会等待fA,全部完成后,通过callback发出

scc和mcc可以自由组合,我希望以此能搭配更灵活的代码。

运行这段测试代码,需要node v0.11.14 $ node --harmony test.js

有一些遗憾的是,我猜Joyent在v0.11加上了generator,竟然没有添加解构赋值。所以,现在还没法写出:

var [err, data] = yield fs.readFile('/test', {encoding:'utf8'}, ctrl);  console.log(err);  console.log(data);

这样的代码, 而只能代之:

var it = yield fs.readFile('/test', {encoding:'utf8'}, ctrl);  console.log(it[0]);  console.log(it[1]);

it 是类似arguments的类数组。


一个更实际的例子:

使用fsmysql异步读取数据

var fs = require('fs'),      pool = require('mysql').createPool({           host: "localhost",          port: 8080,          user: "root",          password: "",          database: "test",          connectionLimit: 10      }),      gpipe = require('gpipe');    gpipe.scc(function* (ctrl) {      var ro = yield fs.readFile('/test', { encoding:'utf8' }, ctrl);      var err = ro[0];      var data = ro[1];      if (err) {          throw err;      }        var wo = yield fs.writeFile('/new', data, { encoding:'utf8' }, ctrl);      var err = wo[0];      if (err) {          throw err;      }        var mo = gpipe.mcc(function* (ctrl) {          yield pool.query('SELECT * FROM employee', ctrl('employee'));          yield pool.query('SELECT * FROM deparment', ctrl('deparment'));          yield pool.query('SELECT * FROM order', ctrl('order'));      }, ctrl);      var employee = mo[0]['employee'];      var deparment = mo[0]['deparment'];      var order = mo[0]['order'];  }, function () {      console.log('complete');  });

项目主页:http://www.open-open.com/lib/view/home/1419300643859