Node.js服務端框架Koa源碼學習

目標

本文主要通過一個簡單的例子來解釋koa的內部原理。

koa的一個簡單例子

<strong>圖1是Koa的一個簡單例子,下文會對這個例子的每行代碼背後的邏輯做詳細分析。

Node.js服務端框架Koa源碼學習

圖1 demo


koa內部文件組成


Node.js服務端框架Koa源碼學習

圖2 Koa代碼文件


Node.js服務端框架Koa源碼學習

圖3 文件和具體類


  • application.js中包含了Application類和一些輔助方法
  • context.js主要作用是承載上下信息,並封裝了處理上下文信息的操作
  • request.js中封裝了處理請求信息的基本操作
  • response.js中封裝了處理響應信息的基本操作

koa內部

在圖1的例子中,執行const app = new koa()時,實際上構造了一個Application實例,<strong>圖4為Application構造方法,構造方法中創建了Context、Request、Response等類的運行實例。關於Context、Response、Request類及方法介紹請參考

https://koajs.com/

下文約定request代指Request類實例,response代指Response類實例,context代指Context類實例。


Node.js服務端框架Koa源碼學習

圖4 Application構造方法


<strong>圖1的例子中調用app.listen(3000)方法監聽3000端口進來的http請求,listen方法內部創建了一個http.Server對象,並調用http.Server的listen方法。具體代碼如<strong>圖5。


Node.js服務端框架Koa源碼學習

圖5 listen犯法


<strong>圖5中this.callback方法的源碼如下<strong>圖6中所示


Node.js服務端框架Koa源碼學習

圖6 callback


callback方法返回一個handleRequest函數,作為createServer的參數,當http.Server實例接收到一個http請求時,會將請求信息和請求響應對象傳給handleRequest函數,具體指將http.IncomingMessage的實例req,和http.ServerResponse的實例res傳給handleRequest函數。其中this.createContext函數的源碼如下<strong>圖7

http.IncomingMessage和http.ServerResponse信息可以參照node.js官網

Node.js服務端框架Koa源碼學習

圖7 createContext


<strong>圖7中createContext的主要作用是將請求信息和響應信息封裝在Request和Response類的運行實例中,並創建上下文類Context實例。context對象包含了Application、Request、Response等實例的引用。在this.callback方法中還有另一行很重要的代碼,如下<strong>代碼片段1。

代碼片段1

<code>const fn = compose(this.middleware);/<code>

可以從<strong>圖4中Application的構造方法中知道this.middleware是一個數組,該數組用來存儲app.use方法傳入的中間件函數。Application的use方法具體代碼實現細節如<strong>圖8,其中最關鍵的一行代碼是this.middleware.push(fn)。


Node.js服務端框架Koa源碼學習

圖8 use


compose方法的代碼實現包含在koa-compose包中,具體代碼實現細節如<strong>圖9


Node.js服務端框架Koa源碼學習

圖9 compose


compose方法接收this.middleware數組,返回一個匿名函數,該函數接收兩個參數,上下文實例context和一個next函數,執行該匿名函數會執行this.middleware數組中的所有中間件函數,然後在執行傳入的next函數。匿名函數調用是在Application的callback方法中,在<strong>圖6

的callback方法的最後將執行上下文對象和compose方法返回的匿名函數作為參數傳入this.handleRequest方法。接下來看一下this.handleRequest方法的具體細節,如<strong>圖9。


Node.js服務端框架Koa源碼學習

圖9 handleRequest


在this.handleRequest方法中創建了錯誤處理方法onError和返回響應的方法

handleResponse。fnMiddleware就是compose方法返回的匿名函數。在this.handleRequest方法的最後執行匿名函數,並傳入hanldeResponse和onError函數分別處理正常請求響應流程和異常情況。

<code>return fnMiddleware(ctx).then(handleResponse).catch(onerror);/<code>

執行fnMiddleware函數,實際上是執行之前傳入所有中間件函數。在中間函數中可以拿到上下文對象的引用,通過上下文對象我們可以獲取到經過封裝的請求和響應實例,具體形式如<strong>圖10。


Node.js服務端框架Koa源碼學習

圖10 中間間函數例子


在中間件方法中可以設置響應頭信息、響應內容。以及讀取數據庫,獲取html模版等。將需要返回給用戶端的數據賦值給上下文對象context的body屬性。respond方法的具體實現如<strong>圖11。


Node.js服務端框架Koa源碼學習

圖11 respond


respond方法的主要作用是對返回的內容進行一些處理,然後調用node.js的http.ServerResponse實例的end方法,將具體內容返回給用戶端。

request.js和response.js

ApplicationcreateContext方法中,將node.js的請求(http.IncomingMessage)和響應對象(http.ServerResponse)分別賦值給了Request類和Response類實例對象。Request中主要包含了處理請求的方法(實際上都是get方法,或者獲取器),獲取請求數據,例子如<strong>圖12。


Node.js服務端框架Koa源碼學習

圖12 host方法例子


上面的代碼中this.reqhttp.IncomingMessage實例,包含了http請求信息。Response中包含了處理請求響應的操作。例如設置響應狀態信息,如<strong>圖13


Node.js服務端框架Koa源碼學習

圖13 status


其中this.reshttp.ServerResponse對象實例。

到此處,圖1中三行代碼的背後邏輯已分析完成。


分享到:


相關文章: