Koa2 和 Express 中介軟體對比

2022-11-14 11:32:33 字數 2923 閱讀 8233

koa2的中介軟體是通過async await實現的,中介軟體執行順序是“洋蔥圈”模型。

中介軟體之間通過next函式聯絡,當一箇中介軟體呼叫next()後,會將控制權交給下一個中介軟體, 直到下一個中介軟體不再執行next()後, 將會沿路折返,將控制權依次交換給前一箇中介軟體。

如圖:

const koa = require('koa');

// logger

console.log('第一層 - 開始')

await next();

const rt = ctx.response.get('x-response-time');

console.log(`$ ----------- $ ----------- $`);

console.log('第一層 - 結束')

});// x-response-time

console.log('第二層 - 開始')

const start = date.now();

await next();

const ms = date.now() - start;

ctx.set('x-response-time', `$ms`);

console.log('第二層 - 結束')

});// response

console.log('第三層 - 開始')

ctx.body = 'hello world';

console.log('第三層 - 結束')

});

第一層 - 開始

第二層 - 開始

第三層 - 開始

第三層 - 結束

第二層 - 結束

列印第一次執行的結果: get -------- /text ------ 4ms

第一層 - 結束

下面是一個登陸驗證的中介軟體:

logincheck.js:

module.exports = async (ctx, next) => 

// 登陸失敗,禁止繼續執行,所以不需要執行 next()

ctx.body =

}

在刪除操作中使用 logincheck.js :

router.post('/delete', logincheck, async (ctx, next) => 

} else }})

與 koa2 中介軟體不同的是,express中介軟體一個接一個的順序執行, 通常會將 response 響應寫在最後一箇中介軟體中

遇到 http 請求,根據 path 和 method 判斷觸發哪些中介軟體

const express = require('express')

console.log('第一層 - 開始')

settimeout(() => , 0)

console.log('第一層 - 結束')

}) console.log('第二層 - 開始')

settimeout(() => , 0)

console.log('第二層 - 結束')

}) console.log('第三層 - 開始')

res.json()

console.log('第三層 - 結束')

}) console.log('server is running on port 3000')

})

第一層 - 開始

第一層 - 結束

第二層 - 開始

第二層 - 結束

第三層 - 開始

第三層 - 結束

因為上面各個中介軟體中的 next() 是非同步執行的,所以 列印結果是線行輸出的。

如果取消上面next()的非同步執行,直接按如下方式:

const express = require('express')

console.log('第一層 - 開始')

next()

console.log('第一層 - 結束')

}) console.log('第二層 - 開始')

next()

console.log('第二層 - 結束')

}) console.log('第三層 - 開始')

res.json()

console.log('第三層 - 結束')

}) console.log('server is running on port 3000')

})

第一層 - 開始

第二層 - 開始

第三層 - 開始

第三層 - 結束

第二層 - 結束

第一層 - 結束

可見,express 的中介軟體也可以形成“洋蔥圈”模型,但是一般在express中不會這麼做,因為 express 的 response 一般在最後一箇中介軟體,所以其它中介軟體 next() 後的**影響不到最終結果。

下面是一個登陸驗證的中介軟體:

logincheck.js:

module.exports = (req, res, next) => 

// 登陸失敗,禁止繼續執行,所以不需要執行 next()

ctx.body =

}

在刪除操作中使用 logincheck.js :

router.post('/delete', logincheck, (req, res, next) => 

} else }})

})