koa-connect源码解析
文中提到的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方法
- Connect 源码解析(一)
- Koa2 源码解析(1)
- 目标--connect world,ZMQ源码详细解析 之 进程内通信流程
- OBS源码解析(3)OBSApp类介绍
- EventBus源码解析 源码阅读记录
- OKHttp源码解析(二)
- Android事件分发机制完全解析,带你从源码的角度彻底理解(下)
- SuperSocket源码解析之开篇 (转)
- jquery源码解析:each,makeArray,merge,grep,map详解
- MyBatis-3.4.2-源码分析1:解析XML之propertiesElement(root.evalNode("properties"))
- Spring源码阅读-- 解析自定义命名空间的标签
- 从源码解析Nginx对 Native aio支持
- Redisson分布式锁源码解析
- 解读QT信号与槽机制里 QMetaObject::connectSlotsByName(QObject *o)的源码
- Volley 源码解析
- JavaScipt 源码解析 回调函数
- spring源码(4)之解析默认命名空间
- Integer源码解析
- MyBatis源码解析(二)——动态代理实现函数调用
- 基于8.0源码解析:startService 启动过程