什么是CO?
co 模块是著名程序员 TJ Holowaychuk 于 2013 年 6 月发布的一个小工具,用于 Generator 函数的自动执行。
复习Generator
generator是ES6提供的一种解决异步编程方案;形式上,Generator 函数是一个普通函数,但是有两个特征。一是,function关键字与函数名之间有一个星号;二是,函数体内部使用yield表达式,定义不同的内部状态(yield在英语里的意思就是“产出”)。
generator总是返回一个指向内部状态的指针对象,然后必须调用该指针对象的next方法是的指针移向下一个状态。
关键字 _yield 是暂停执行标志,_而_next_方法是可以恢复执行
开始学习CO
co接受Generator函数作为参数,通过return一个Promise方式来交回执行权。
function co(gen) {
var ctx = this;
return new Promise(function(resolve, reject) {
});
}
然后在Promise对象里面判断参数gen是否为Generator函数,如果是则执行否则直接resove出该参数
function co(gen) {
var ctx = this
var args = slice.call(arguments, 1)
return new Promise(function (resolve, reject) {
if(typeof gen === 'function') gen = gen.apply(ctx)
if(!gen || typeof gen.next !== 'function') resolve(gen)
})
}
封装onFulfilled函数能够捕捉抛出错误
function onFulfilled(res) {
var ret;
try {
ret = gen.next(res);
} catch (e) {
return reject(e);
}
next(ret);
}
最后就是next函数,递归调用自身来达到自动执行next方法目的
function next(ret) {
if (ret.done) return resolve(ret.value);
var value = toPromise.call(ctx, ret.value);
if (value && isPromise(value)) return value.then(onFulfilled, onRejected);
return onRejected(
new TypeError(
'You may only yield a function, promise, generator, array, or object, '
+ 'but the following object was passed: "'
+ String(ret.value)
+ '"'
)
);
}
总结
co函数接收一个Generator函数当做形参,然后执行next方法,根据done判断何时执行resove方法,通过每次Promise执行完then函数后回调onFulfilled递归执行next方法,通过next方法传递上一个状态值。
公共函数
toPromise、thunkToPromise、arrayToPromise、objectToPromise、defer、 isPromise、isGenerator、isGeneratorFunction、isObject