koa 是由 Express 原班人馬打造的,致力於成爲一個更小、更富有表現力、更健壯的 Web 框架。使用 koa 編寫 web 應用,經過組合不一樣的 generator,能夠免除重複繁瑣的回調函數嵌套,並極大地提高錯誤處理的效率。koa 不在內核方法中綁定任何中間件,它僅僅提供了一個輕量優雅的函數庫,使得編寫 Web 應用變得駕輕就熟。git
koa自己相較於其餘web框架來講更輕量。可是若是要實現更健壯的服務,咱們就須要添加大量的中間件來豐富咱們的服務! 因此對比其餘web框架,koa有本身獨特的處理中間件的方式-->compose!github
compose的源碼並很少,二十幾行,那它是如何實現你們所認爲的洋蔥模型呢web
探索源碼前咱們先定義下當前的場景,以便於更好的描述數組
const Koa = require('koa');
const app = new Koa();
app.use(async (ctx, next) => {
console.log(1);
await next();
console.log(1.1)
})
app.use(async (ctx, next) => {
console.log(2)
await next();
console.log(2.1)
})
app.use(async (ctx, next) => {
console.log(3)
await next();
console.log(3.1)
})
app.listen(8080, () => {
console.log('8080')
})
// 輸出結果 1-->2-->3-->3.1-->2.1-->1.1
複製代碼
源碼地址bash
// 這是我簡化一部分異常處理後的源碼
// middleware 爲存放中間件函數的數組
function compose (middleware) {
return function (context, next) {
let index = -1
return dispatch(0)
function dispatch (i) {
index = i
let fn = middleware[i]
if (i === middleware.length) fn = next
if (!fn) return Promise.resolve()
return Promise.resolve(fn(context, function next () {
return dispatch(i + 1)
}))
}
}
}
複製代碼
分析調用的過程:app
我這裏實現了一個簡單版的中間件處理邏輯,根據這個幫咱們更好的去理解compose框架
function compose(middleware) {
dispatch(0);
function dispatch(idx) {
middleware[idx](ctx, () => dispatch(idx + 1));
}
}
複製代碼
聽過上述的分析,相信你們對Koa的中間件處理有了必定的認識;看起來Koa的中間件處理就是一個洋蔥模型,可是在某種狀況下,可能這個洋蔥模型是不完整,由於有些時候程序不會走完整個中間件的處理,可能在第一個或中間某個中間就已經結束了。koa