標籤:includes receiving sum com const 返回 說明 app handler
文中提到的koa均為koa2
提到nodejs, 想必大家都知道express和koa.
express: 大
koa: 小
比較的的是功能, 社區, 中介軟體,相關資源等
這裡我就專門說說中介軟體吧, 很多人可能說express外掛程式豐富啊. 其實除了中介軟體, 其餘什麼的和express koa本身並沒有多大關係, 不都是基於nodejs http(https)的封裝嘛.
express中介軟體是非常的豐富, 但是提個醒, express的中介軟體是可以跑在koa下面的.到這裡就要提到 koa-connect.
那麼,我們就來簡單看看這個koa-connect是怎麼實現的.
其源碼一共才38行, 一半多注釋, 3個方法.
- koaConnect: 對外公布的方法, 對express的中介軟體的參數進行分析,分別調用noCallbackHandler和withCallbackHandler
- noCallbackHandler : 處理無回調的express的中介軟體
- withCallbackHandler : 處理有回調的express的中介軟體
這裡的回調就是有無next方法, next方法就是進入下一個中介軟體
/** * If the middleware function does declare receiving the `next` callback * assume that it‘s synchronous and invoke `next` ourselves */function noCallbackHandler(ctx, connectMiddleware, next) { connectMiddleware(ctx.req, ctx.res) return next()}/** * The middleware function does include the `next` callback so only resolve * the Promise when it‘s called. If it‘s never called, the middleware stack * completion will stall */function withCallbackHandler(ctx, connectMiddleware, next) { return new Promise((resolve, reject) => { connectMiddleware(ctx.req, ctx.res, err => { if (err) reject(err) else resolve(next()) }) })}/** * Returns a Koa middleware function that varies its async logic based on if the * given middleware function declares at least 3 parameters, i.e. includes * the `next` callback function */function koaConnect(connectMiddleware) { const handler = connectMiddleware.length < 3 ? noCallbackHandler : withCallbackHandler return function koaConnect(ctx, next) { return handler(ctx, connectMiddleware, next) }}module.exports = koaConnect
koaConnect方法
function koaConnect(connectMiddleware) { const handler = connectMiddleware.length < 3 ? noCallbackHandler : withCallbackHandler return function koaConnect(ctx, next) { return handler(ctx, connectMiddleware, next) }}
kaoConnect返回的是一個koa版本的中介軟體.
connectMiddleware.length是express中介軟體參數的長度, 如果你這個中介軟體使用了arguments進行參數解析或者使用了rest參數, 那麼這個length本身就準確了.
通過express中介軟體參數的長度分別調用有回調和無回調的方法.
noCallbackHandler方法
function noCallbackHandler(ctx, connectMiddleware, next) { connectMiddleware(ctx.req, ctx.res) return next()}
直接調用express方法, ctx.req 和 ctx.res作為參數傳入.
ctx.req: Node 的 request 對象.
ctx.res: Node 的 Reponse 對象.
這說明express的中間的req 和 res 和koa中介軟體的ctx.req 和res就是一個玩意.
因為express中介軟體沒有調用next, 所以被調用完畢, 直接調用koa中介軟體的next
withCallbackHandler方法
function withCallbackHandler(ctx, connectMiddleware, next) { return new Promise((resolve, reject) => { connectMiddleware(ctx.req, ctx.res, err => { if (err) reject(err) else resolve(next()) }) })}
返回一個Promise, 因為koa中有 await next()的形式調用, 這就很好的滿足了需求.
express中間裡面假如有第三個參數next,調用表示進入下一個中介軟體.
express中介軟體next調用的時候可以傳入Error,
可以參考express error handling
app.get("/", function (req, res, next) { fs.readFile("/file-does-not-exist", function (err, data) { if (err) { next(err); // Pass errors to Express. } else { res.send(data); } });});
回到我們的withCallbackHandler方法
這裡express的中介軟體的next方法即為
err => { if (err) reject(err) else resolve(next()) }
當有錯誤的時候,reject
當沒有錯誤的時候, 調用koa中介軟體的next, 繼續下面的執行.
koa-connect就分析完畢了, 核心就兩點
- 通過express中介軟體的參數長度來區分處理
- 改造express中介軟體的next方法
koa-connect源碼解析