再說co之前要先搞清楚 Thunk函數(shù)和 Generator函數(shù)
Generator函數(shù):
function* gen(x){
var y = yield x + 2;
return y;
}
var g = gen(1);
g.next() // { value: 3, done: false }
g.next() // { value: undefined, done: true }
簡(jiǎn)單來說Generator 可以讓你擁有函數(shù)的控制權(quán)桩匪。上面代碼中g(shù)en函數(shù)返回一個(gè)對(duì)象,這個(gè)對(duì)象中有value 和dong 兩個(gè)值友鼻, value就是 函數(shù)中 yield 后面語句的值傻昙,而done 則用來判斷函數(shù)時(shí)候執(zhí)行完闺骚。你可以通過next()函數(shù)來執(zhí)行代碼,每次調(diào)用next 函數(shù)都會(huì)執(zhí)行到 yield 并且返回后面語句的值妆档。
Thunk函數(shù):
// 正常版本的readFile(多參數(shù)版本)
fs.readFile(fileName, callback);
// Thunk版本的readFile(單參數(shù)版本)
var readFileThunk = Thunk(fileName);
readFileThunk(callback);
var Thunk = function (fileName){
return function (callback){
return fs.readFile(fileName, callback);
};
};
Thunk 可以讓你把一個(gè)接受多參數(shù)的函數(shù)(至少要用一個(gè)回調(diào)函數(shù)作為參數(shù))變成 接受單參數(shù)的函數(shù)僻爽。 上面代碼中先用 Thunk函數(shù) 固定來一個(gè)參數(shù) 然后返回一個(gè)函數(shù)。這樣过吻,這個(gè)函數(shù)就只要接受一個(gè)回調(diào)作為參數(shù)进泼。
Generator 跟 Thunk 配合使用 可以實(shí)現(xiàn) Generator 函數(shù)自動(dòng)執(zhí)行
co是干啥用的
co 可以幫你自動(dòng)執(zhí)行Generator
直接看源碼:
function co(gen) {
var ctx = this;
return new Promise(function(resolve, reject) {
if (typeof gen === 'function') gen = gen.call(ctx);
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);
}
});
}
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 函數(shù)接受 Generator 函數(shù)作為參數(shù),返回一個(gè) Promise 對(duì)象纤虽。
然后 在Promise中 需要判斷一下 參數(shù)是不是Generator 函數(shù)乳绕,如果是就執(zhí)行這個(gè)函數(shù)。這樣就會(huì)得到一個(gè)新的對(duì)象逼纸,你可以通過這個(gè)對(duì)象的next 控制Generator 函數(shù)的執(zhí)行洋措,如果不是就返回,并將 Promise 對(duì)象的狀態(tài)改為 resolved 杰刽。
onFulfilled 函數(shù)會(huì)調(diào)用上面返回的對(duì)象的next函數(shù)讓Generator 函數(shù)進(jìn)行下一步菠发, onFulfilled 函數(shù)中用來try...catch 來捕獲錯(cuò)誤。
最后會(huì)執(zhí)行next(ret) 這里的ret 是把上一階段處理完畢的異步結(jié)果傳入next函數(shù)贺嫂。
next函數(shù)先通過參數(shù)中的done 來判斷是否是Generator 函數(shù)的最后一步滓鸠,如果是就返回。
然后給了確保 參數(shù)是Promise對(duì)象 把參數(shù)轉(zhuǎn)換為Promise對(duì)象
使用then 傳入兩個(gè)回調(diào) 如果成功 就調(diào)用onFulfilled (調(diào)用自身)
如果失敗 拋出一個(gè)錯(cuò)誤第喳,并且終止執(zhí)行糜俗。