koa中間件之compose

koa

koa 是由 Express 原班人馬打造的,致力於成爲一個更小、更富有表現力、更健壯的 Web 框架。使用 koa 編寫 web 應用,經過組合不一樣的 generator,能夠免除重複繁瑣的回調函數嵌套,並極大地提高錯誤處理的效率。koa 不在內核方法中綁定任何中間件,它僅僅提供了一個輕量優雅的函數庫,使得編寫 Web 應用變得駕輕就熟。git

核心-compose

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

  • 一、取出middleware中的第一個中間件函數而且用Promise.resolve包裝一下執行,執行的時候傳入context上下文和next函數
  • 二、next的函數體內容實際就是調用第二個被Promise.resolve包裝後的中間件函數,因此,當定義的中間函數調用next()方法的時候實際是去調用第二個中間件函數執行了,而且咱們發現,全部的中間件函數都是被包裝在Promise.resolve中執行;因此咱們能夠在中間件函數中 await next()
  • 三、當middle中最後一箇中間件函數調用完畢後,根據代碼從上往下執行的邏輯,會依次往前執行其餘中間件next後邊的代碼
簡單版實現compose

我這裏實現了一個簡單版的中間件處理邏輯,根據這個幫咱們更好的去理解compose框架

function compose(middleware) {
    dispatch(0);
    function dispatch(idx) {
        middleware[idx](ctx, () => dispatch(idx + 1));
    }
}
複製代碼

結論

聽過上述的分析,相信你們對Koa的中間件處理有了必定的認識;看起來Koa的中間件處理就是一個洋蔥模型,可是在某種狀況下,可能這個洋蔥模型是不完整,由於有些時候程序不會走完整個中間件的處理,可能在第一個或中間某個中間就已經結束了。koa

相關文章
相關標籤/搜索