co源码解读
最近在學(xué)習(xí)使用Koa.在看官網(wǎng)的例子的時(shí)候時(shí)候看到它的中間件的級(jí)聯(lián)模式是通過(guò)生成器實(shí)現(xiàn)的,之后了解到Koa的級(jí)聯(lián)是通過(guò)Co這個(gè)庫(kù)實(shí)現(xiàn)的,下面就是對(duì)這個(gè)庫(kù)的代碼的主要流程的部分解讀
1.生成器基礎(chǔ)
2.代碼解讀
1.生成器基礎(chǔ)
這個(gè)是infoq的深入淺出ES6中生成器的一章 ? 生成器基礎(chǔ)
?
可以通過(guò)下面的代碼片段去大致的理解Co函數(shù)的執(zhí)行過(guò)程 ?生成器可以通過(guò)next來(lái)實(shí)現(xiàn)任務(wù)的串行執(zhí)行 ?next方法返回一個(gè)對(duì)象 有value屬性(yield執(zhí)行的值) done 是否還有未執(zhí)行的yield邏輯 同時(shí)還能將參數(shù)通過(guò)next進(jìn)行傳遞 供下面的邏輯調(diào)用
?
function *test() {var x = yield 1;yield console.log(x); }var a = test(); var temp = a.next(); a.next(temp.value) //1 View Code?
2. 代碼解讀部分
function objectToPromise(obj){var results = new obj.constructor();var keys = Object.keys(obj); //Object.keys()返回一個(gè)對(duì)象所有可枚舉屬性的數(shù)組var promises = [];//保存對(duì)象中promise運(yùn)行的結(jié)果for (var i = 0; i < keys.length; i++) {var key = keys[i];// var promise = toPromise.call(this, obj[key]);if (promise && isPromise(promise)) defer(promise, key);//將原對(duì)象屬性中Promise的與數(shù)組關(guān)聯(lián)else results[key] = obj[key];}return Promise.all(promises).then(function () {return results;});//Promise接受一個(gè)Promise對(duì)象的數(shù)組作為參數(shù) 當(dāng)數(shù)組里面全部變成resolve或者reject狀態(tài)function defer(promise, key) {// predefine the key in the resultresults[key] = undefined;promises.push(promise.then(function (res) {results[key] = res; //romise的then方法不僅僅是注冊(cè)resolve的回調(diào) 還會(huì)將回調(diào)函數(shù)的返回值進(jìn)行變換 返回promsie對(duì)象}));} } View Code?Co將中間的結(jié)果和函數(shù)都進(jìn)行了Promise的封裝 ?主要看下這個(gè)objectToPromise(obj) ?功能就是將一個(gè)對(duì)象轉(zhuǎn)換為Promise對(duì)象 這里需要理解這兩個(gè)方法 Promise.all ?它接受一個(gè)Promsie數(shù)組 當(dāng)數(shù)組中全部為resolve時(shí),它就變成resolve,當(dāng)其中有一個(gè)出現(xiàn)reject的時(shí)候,就進(jìn)入reject狀態(tài)??梢酝ㄟ^(guò)下面的代碼簡(jiǎn)單的理解它的使用
var promise1 = new Promise(function(resolve,reject){resolve(1); }); var promise2 = new Promise(function(resolve,reject){resolve(2); }); Promise.all([promise1,promise2]).then(function(){console.log('ok'); }); View Code接下來(lái)說(shuō)說(shuō)這個(gè)defer(promise,key) 它的功能就是將原來(lái)對(duì)象的值裝換為promise之后,通過(guò)數(shù)組的方式傳遞給外部
function defer(promise, key) {// predefine the key in the resultresults[key] = undefined;promises.push(promise.then(function (res) {results[key] = res; promise的then方法不僅僅是注冊(cè)resolve的回調(diào) 還會(huì)將回調(diào)函數(shù)的返回值進(jìn)行變換 返回promsie對(duì)象}));} View Codepromise.then ?這個(gè)方法是返回一個(gè)Promise對(duì)象 這樣通過(guò)then方法將所有鍵值的執(zhí)行結(jié)果都轉(zhuǎn)換為Promsie對(duì)象 在通過(guò)數(shù)組的方式傳遞給外部 當(dāng)所有鍵值執(zhí)行都為resolve的時(shí)候 就將整體的結(jié)果返回給外部 也就完成了對(duì)obj對(duì)象的封裝。
下面就來(lái)理解下Co函數(shù)
function co(gen) {var ctx = this;var args = slice.call(arguments, 1);// we wrap everything in a promise to avoid promise chaining,// which leads to memory leak errors.// see https://github.com/tj/co/issues/180return new Promise(function(resolve, reject) {if (typeof gen === 'function') gen = gen.apply(ctx, args);if (!gen || typeof gen.next !== 'function') return resolve(gen);onFulfilled();/*** @param {Mixed} res* @return {Promise}* @api private*/function onFulfilled(res) {var ret;try {ret = gen.next(res);} catch (e) {return reject(e);}next(ret);return null;}/*** @param {Error} err* @return {Promise}* @api private*/function onRejected(err) {var ret;try {ret = gen.throw(err);} catch (e) {return reject(e);}next(ret);}/*** Get the next value in the generator,* return a promise.** @param {Object} ret* @return {Promise}* @api private*///co函數(shù)的核心就是這個(gè)next理解 通過(guò)next傳遞將上一個(gè)generator執(zhí)行的結(jié)果往下傳遞并且進(jìn)行了Promise的封裝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) + '"'));}}); } View Code參考 ?Generator與異步編程? ?Co
?
?
?轉(zhuǎn)載于:https://www.cnblogs.com/tiantianwaigong/p/6441723.html
總結(jié)
- 上一篇: 理解原理的重要性 - 论PostgreS
- 下一篇: 第一个程序实现登录功能,密码输错三次封账