Generator 和 yield

es6 有一个 generator 函数,它是一个普通函数,但是有两个特征。一是,function关键字与函数名之间有一个星号;二是,函数体内部使用yield语句,定义不同的内部状态

每次执行 generator 函数会返回一个 iterator,在有 yield 的关键字停止,所以每次执行一次 iterator.next 会在下一个 yield 停止,可以通过 next(val) 把结果返回出来

根据这个原理来实现一个简单的 co 函数

function co(gen) {
var g = gen();
var next = g.next();
var res = next.value;
function _next(next, res) {
if (!next.done) {
if (res && res.constructor == Promise) {
res.then(function (val) {
next = g.next(val);
res = next.value;
_next(next, res);
});
} else if (res.constructor == Function) {
var fn = res;
fn(function (err, res) {
next = g.next(res);
res = next.value;
_next(next, res);
});
} else {
next = g.next(res);
res = next.value;
_next(next, res);
}
}
}
_next(next, res);
}

测试一下~

var fs = require("fs");
var readThunk = thunkify(fs.readFile);
co(function * gen() {
var pro = new Promise(function(resolve, reject) {
resolve(1999);
});
var r3= yield pro;
var r1 = yield 100;
var r2 = yield 200;
var a = yield readThunk("./a.html");
var c = yield function (fn) {
setTimeout(function() {
fn(null, 188);
}, 1000)
}
console.log(r3, r1, r2, a);
console.log(c);
})
// 结果
1999 100 200
188