理解 Koa 的中間件機制(源碼分析)
閱讀源碼,化繁為簡,我們看看 koa 的中間件系統(tǒng)是如何實現(xiàn)的。
class Application extends Emitter { constructor() { super(); this.middleware = []; }, use(fn) { this.middleware.push(fn); return this; }, callback() { const fn = compose(this.middleware); return function(req, res) { return fn(ctx); }; }, listen(...args) { const server = http.createServer(this.callback()); return server.listen(...args); } }
好了,精簡結(jié)束,一不小心,去枝末節(jié),最后只剩下不到 20 行代碼。
這就是框架的核心,簡化后的代碼非常清晰,有點不可思議,但核心就是這么簡單。
我們先分析以上代碼做了什么事。
你一定對中間的 compose 方法很好奇,初此之外的代碼都容易理解,唯獨這個 compose 不太知道究竟做了什么。
其實, compose 就是整個中間件框架的核心。
compose 之外,代碼已經(jīng)很清楚的定義了
而 compose 方法做了最為重要的一件事
核心源碼 compose
先上碼
function compose(middleware) { return function(context, next) { // last called middleware # let index = -1; return dispatch(0); function dispatch(i) { if (i <= index) return Promise.reject(new Error("next() called multiple times")); index = i; let fn = middleware[i]; if (i === middleware.length) fn = next; if (!fn) return Promise.resolve(); try { return Promise.resolve(fn(context, dispatch.bind(null, i + 1))); } catch (err) { return Promise.reject(err); } } }; }
我試圖去簡化一下這個方法,但方法本身已經(jīng)足夠簡潔。
代碼很簡潔。
通過 next()傳遞 實現(xiàn)中間件調(diào)用, 結(jié)合 Promise 采用 遞歸調(diào)用 的通知機制。
看圖
這種形式的控制流讓整個 Koa 框架中間件的訪問呈現(xiàn)出 自上而下的中間件流 + 自下而上的 response 數(shù)據(jù)流 的形式。
Koa 本身做的工作僅僅是定制了中間件的編寫規(guī)范,而不內(nèi)置任何中間件。一個 web request 會通過 Koa 的中間件棧,來動態(tài)完成 response 的處理。
koa 在中間件語法上面采用了 async + await 語法來生成 Promise 形式的程序控制流。
總結(jié)
koa 是非常精簡的框架, 其中的精粹思想就是洋蔥模型(中間件模型), koa 框架的中間件模型非常好用并且簡潔, 但是也有自身的缺陷, 一旦中間件數(shù)組過于龐大, 性能會有所下降,我們需要結(jié)合自身的情況與業(yè)務(wù)場景作出最合適的選擇.
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com