中間件模式是現現在各個框架——尤爲是 Web 框架使用得較多的一種開發模式。譬如大名鼎鼎的 Express, Koa 等均使用中間件來處理請求。那麼,何爲中間件模式呢?javascript
處理 Web 請求時,咱們經常須要進行驗證請求來源、檢查登陸狀態、肯定是否有足夠權限、打印日誌等操做,而這些重複的操做若是寫在具體的路由處理函數中,明顯會致使代碼冗餘,這個時候,咱們就能夠將這些通用的流程抽象爲中間件函數,減小重複代碼。html
咱們能夠將 Web 請求想象爲一條串聯的管道,在管道中有多個關卡,請求數據由源頭起,依次流過各關卡,每一個關卡獨立運做,既能夠直接響應數據,又能夠對請求稍做調整,並使之流向下一關卡,這個關卡,就是中間件。java
咱們以 Koa 的中間件爲例。git
router
.get('/users', loginChecker, async ctx => {
const users = await db.getUsers()
ctx.body = users
})
.delete('/users/:id', adminChecker, async ctx => {
const { id } = ctx.params
await db.deleteUserById(id)
ctx.body = { error: false }
})
複製代碼
咱們使用 loginChecker
來檢查用戶是否登陸,而對於高風險的刪除操做,咱們使用 adminChecker
來判斷用戶是否有管理員權限。github
誠如你如看到的,咱們在編寫具體的路由處理函數時,只需考慮事務邏輯,大大下降了心智負擔。咱們甚至能夠在最外層套一個錯誤處理中間件,catch
住全部異常,統一處理——這也是我爲何不在使用 await
時包裝一層 try/catch
。express
咱們不討論怎麼開發 Koa 中間件,咱們來談一下如何實現中間件模式。小程序
Koa 實現了基於洋蔥模型的中間件,在處理請求時,老是從外層中間件開始,到最內層,最後回到最外層。基於這個結論,咱們能夠使用一個數組來順序存儲中間件,並依次調用。微信小程序
async function exec(middlewares, ctx) {
let index = 0
const next = async () => {
const current = middlewares[index++]
if (current) {
await current(ctx, next)
}
}
await next()
}
const ware1 = async (ctx, next) => {
ctx.body = 'This is ware 1'
await next()
console.log("ware1 is back")
}
// 不調用 next,則不會進入下箇中間件
const ware2 = async (next) => {
ctx.body = 'Hello, world'
}
複製代碼
ctx
意爲上下文(Context),是中間件通訊的橋樑,各中間件經過修改 ctx
來返回數據。如 Koa
就是經過修改 ctx.body
來改變響應體的。數組
經過向當前中間件傳遞調用 next 方法,來控制中間件執行的過程,實現了洋蔥模型。值得注意的是,ware2
中未調用 next
方法,所以無論它後面是否還有其它中間件,它都會成爲洋蔥模型中的最裏層,隨後會回到外層的中間件去。微信
本文介紹了什麼是中間件,並附上簡單的實現。若是你是微信小程序開發者,能夠參考我使用中間件模式開發的小程序請求庫 minapp-request,瞭解更完整的代碼實現。
喜歡請點個贊,能關注一下就更好啦。