如何理解 koa 中間件執行機制

前幾天研究了TJ的koa/co4.x和一系列koa依賴的源碼,在知乎上作出了人生首次回答(並且我真得不再想去知乎回答技術問題了_(:з」∠)_),所以把文字搬到這裏。前端

ES2015 Generator/Yield

關於Generator/Yield 這幾篇文章已經寫得足夠清晰了:node

Koa的運行機制

簡單地畫了一張圖解釋koa的處理流程:python

圖片描述

在koa裏定義的middleware均爲generator function(包括內置在頂端的respond),這是爲了能從任意middleware中容易地切換到其它middleware裏(若是你是前端程序員,能夠理解爲瀏覽器捕獲事件的capture和propagation過程,若是你是python程序員,能夠理解爲jungle的middleware機制,若是你是Java程序員,這種方式則是典型的切面編程)。git

爲了實現這種橫穿多個middleware的特性,koa經過把後一個generator做爲參數(koa裏經常使用next)傳入前一個generator實現(#見koa-compose源碼,這也是爲何前兩個middleware有next參數而最後一個沒有)。程序員

能夠看到,在koa中yield的使用是在co,而co則是包裝了generator/yield & Promise以模擬async/await,提供了一個更高層次的異步語法抽象。es6

koa在加載且合併全部的middleware以後,傳遞給co執行(確切地說是在http.createServer的callback觸發後執行),co以圖中所示邏輯不斷拆解generator function,執行yield右側固定的幾種表達式(Array,Object,generator function,Promise,thunkify function),這5種表達式最終都會轉化爲Promise,以達處處理異步函數的目的。github

co內部封裝了onFulfilled和onRejected函數,當yield右側的promise resolve以後,則會調用onFullfield函數,其包含了一條關鍵語句gen.next(res)#這句代碼 用以給yield表達式賦值並執行下一次迭代。編程

koa經過上文的方式「深刻」->「淺出」,最終在頂層的respond middleware裏send response。promise

注:#thunk是co先前版本處理異步函數的方式,經過thunk能夠將異步函數封裝成curry,傳入普通參數後造成僅須要callback參數的偏函數,以此簡化callback調用代碼(目前co中的thunk偏函數已經被#無情地Promise化了)。瀏覽器

by Abruzzi's blog

相關文章
相關標籤/搜索