本文的示例代碼參考co
目錄
Generator
function* foo() {
yield console.log('1');
yield console.log('2');
}
var g = foo();
g.next(); // 1
g.next(); // 2
更多關(guān)于Generator函數(shù)可以參考Generator 函數(shù)的語法
co
cnpm i --save co
var co = require('co');
function* foo() {
yield Promise.resolve(console.log('1'));
yield Promise.resolve(console.log('2'));
}
co(foo); // 1 2
co適用于: Generator函數(shù)的yield命令后面 只能是Thunk函數(shù)或Promises對象
Source Code
- co實現(xiàn)的核心代碼只有以下的區(qū)區(qū)40行
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, args);
if (!gen || typeof gen.next !== 'function') return resolve(gen);
onFulfilled();
function onFulfilled(res) {
var ret;
try {
ret = gen.next(res);
} catch (e) {
return reject(e);
}
next(ret);
return null;
}
function onRejected(err) {
var ret;
try {
ret = gen.throw(err);
} catch (e) {
return reject(e);
}
next(ret);
}
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) + '"'));
}
});
}
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;
}
更多關(guān)于co的源碼可以參考co/index.js
- 完整的流程示意圖如下
co-logic-01.png
更多關(guān)于Promise可以參考Promise 對象