使用 Generator 简化异步回调
1 2 3 4 5 6 7 8 9 10 11 12 13
| var gen; function async() { setTimeout(function () { gen.next(100); }); } function * genFn() { var res = yield async(); console.log('res is: ' + res); }
gen = genFn(); gen.next();
|
输出的结果是
如果将后面的 .next()
封装起来,就变成这样
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| var activeGenerator;
function gNext() { return function (err, data) { if (err) { throw err; } activeGenerator.next(data) } }
function gQueue(generatorFunc) { activeGenerator = generatorFunc(gNext()); activeGenerator.next(); }
function asyncFunc(cb) { setTimeout(function() { cb(null, 100); }, 1000) }
gQueue(function * flow(next) { console.log('start');
var y = yield asyncFunc(next);
console.log('y is', y);
var z = yield asyncFunc(next); console.log('z is ', z);
console.log('end') });
|
参考文章: 使用 (Generator) 生成器解决 JavaScript 回调嵌套问题
Koa 中的应用
koa 使用的就是上面的原理,按照 co 的用法,就可以这样
main.js
1 2 3 4 5 6 7 8 9 10 11
|
var template = require('./template');
app.use(function * (next) { yield next; this.body = yield template.tpl('tplName'); });
|
template.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| exports.tpl = function (path) { return function (cb) { var tmpl = new Template(path); tmpl.on('success', function (res) { cb(null, res); }); tmpl.on('error', function (err) { cb(err, null); }); }; };
|
注意到 gNext
输出的是如下形式的 function
1 2 3
| function (err, data) { }
|
因此 template.js
中的 cb 便是上述形式。
参考文章: 探索Javascript异步编程