function onFulfilled(res) {
var ret
try {
ret = gen.next(res);
} catch (e) {
return reject(e);
}
next(ret);
return null
}
reject则通过throw来将错误抛出
对于next函数的实现:
//获取generator next的值,并返回Promise
function next(ret) {
if (ret.done) return resolve(ret.value);//如果迭代器结束,则将值作为resolve的参数传递出去,可以在.then中获取到
var value = toPromise.call(ctx, ret.value);//ctx代表当前环境对象,window or global
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) + '"'));
}
//将yield产出的值转为Promise的值
function toPromise(obj) {
if (!obj) return obj;
if (isPromise(obj)) return obj;
if (isGeneratorFunction(obj) || isGenerator(obj)) return co.call(this, obj);
if ('function' == typeof obj) return thunkToPromise.call(this, obj);
if (Array.isArray(obj)) return arrayToPromise.call(this, obj);
if (isObject(obj)) return objectToPromise.call(this, obj);
return obj;
}
co 函数库是一个中间产品,co是coroutine的缩写,即协同程序。co可以说是给generator增加了promise实现。co是利用Generator的方式实现了
async/await
co函数库对外暴露的方法只有两个:
其中,
fn *
代表Generator函数。看一个官方文档中的例子:co函数接收一个
Generator
函数作为参数。执行co函数的时候,生成器函数内部的逻辑像async函数调用时一样被执行。不同之处只是这里的await变成了yield(产出)。async和co一样,都返回了Promise对象,都可以链式调用.then()
方法关于Generator 函数,我们可以看一个例子:
gen.next()的返回对象格式如下:
done 表示迭代器是否结束,value 表示yield后面语句的返回值。co用到的一些特性:
gen.next()
和yield配合使用,以yield为界分段执行gen.next(value)
用异步操作结果(value)改写前一个yield的 valuegen.throw(error)
抛出错误可在generator内部捕获co内部定义了co函数,通过返回
new Promise()
对象,实现了链式调用。一个Generator内部可能有多个yield,一个yield结束之后会执行下一个yield,这个过程通过递归实现:
reject则通过throw来将错误抛出
对于next函数的实现:
所以其实co函数库只是内部封装了Generator函数和自动执行器(通过递归调用实现),并返回了Promise对象。使其可以和async一样,做到“同步调用,异步执行”
传入一个generator,返回一个普通函数,这个函数会返回一个Promise。
由于声明式函数具有提升作用,所以createPromise可以在上面调用,而createPromise函数则是:
其中,
fn.apply(this, arguments)
则是: