Koa原始碼分析(二) co的實現

2021-09-16 23:39:39 字數 2312 閱讀 1997

koa原始碼分析(一) -- generator

koa原始碼分析(二) -- co的實現

koa原始碼分析(三) -- middleware機制的實現

大名鼎鼎的co是什麼?它是tj大神基於es6的一些新特性開發的非同步流程控制庫,基於它所開發的koa被視為未來主流的web框架。

koa基於co實現,而co又是使用了es6的generator和promise特性。如果還不理解,可以檢視阮一峰老師的《ecmascript 6 入門 --- generator》和《ecmascript 6 入門 --- promise》。目前co公升級為4.x版本事,**進行了一次頗有規模的重構,我們主要關注co(4.x)的實現思路和原始碼分析。

co(function* ()).then((value) => console.log(value));

// one

// two

// three

co(function* ()).then((value) => console.log(res));

// [1, 2, 3]

根據co的功能,它作為非同步流程控制的作用,自動呼叫generator物件的next()方法,實現generator函式的執行,並返回最終執行的結果。

如果要涉及到co的實現細節,我們就會存在以下幾個疑問:

如何依次呼叫next()方法

如何將yield後邊運算非同步結果返回給對應的變數

co自身如何返回generator函式最後的return值

接下來我們正對以上問題,分析tj大神的原始碼

co原始碼的流程控制

function co(gen)  catch (e) 

// 將gen.next的執行結果傳入next函式,實現依次序列呼叫gen.next方法

next(ret);

return null;

}// 當做所有內部promise物件的reject方法,處理非同步結果,並繼續呼叫下乙個promise

function onrejected(err) catch (e)

// 將gen.throw的執行結果傳入next函式,實現依次序列呼叫gen.next方法

next(ret);

}// 實現序列呼叫gen.next的核心

function next(ret)

});}

原始碼分析完了,我們可以把co序列呼叫generator函式中yield的過程總結如下:

進入外圍promise

通過入口onfilfilled()方法,將generator函式執行至第乙個yield處,執行該yield後邊的非同步操作,並將結果傳入next方法

如果next中傳入結果的done為true,則返回外圍promise的resolve

如果next中傳入結果的done為true,則返回value(即yield後邊的物件)是否可以轉化為內部promise物件。如無法轉化,則丟擲錯誤,返回外圍promise的reject

若能轉化為promise物件,將所有內部promise並行執行,通過then(onfilfilled, onrejected)開始執行

在onfilfilled()或者onrejected()內部呼叫再次呼叫next()方法,實現序列執行yield,並肩yield後邊的物件傳遞給next(),依次重複。

所有yield執行返回,將最後的return值返回給外圍promise的resovle方法,結束co對generator函式的呼叫

yield後面物件轉化為promise

能夠在co中實現generator函式的逐步呼叫next()方法,轉化為內部promise將至關重要,而原始碼是如何轉化的呢?哪些物件又是能夠轉化的呢?接下來,我們看下原始碼。

function topromise(obj) 

function thunktopromise(fn) );

});}function arraytopromise(obj)

function objecttopromise(obj)

// promise鏈式呼叫,後續的then能偶獲取此處的results

return promise.all(promises).then(function () );

function defer(promise, key) ));

}}

結合上述分析,我們可以得到,yield後面只能是函式、promise物件、generator函式、generator迭代器物件、陣列(元素僅限之前的4類)和object(對應value僅限定之前的4類)

Koa原始碼分析

上篇文章寫了如何閱讀koa的原始碼,粗略的過了一下koa的原始碼,但是作為乙個沒有得出乙個具體的結論,中介軟體的執行原理也不清楚,這裡我們再仔細的過一遍koa的原始碼.首先還是先過一遍例子 const koa require koa ctx.body hello world 複製 起乙個web服務,...

Koa原始碼分析

先看看這個極簡的啟動 const koa require koa response ctx.body hello koa 我們在koa原始碼資料夾下建立index.js檔案,將上面的 寫入,並將require koa 換成require const koa require debugger ctx....

koa 原始碼分析

koa的用法,這裡就不在列舉了。我覺得koa主要功能主要是下面幾個方面 1 提供了中介軟體機制 2 封裝了request response,context物件 3 使用了yield,提供了便利的流程控制,使非同步程式設計更優雅 4 便捷的異常處理,使用try catch就可以捕獲程式中的異常,不需要...