• 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就分析完毕了, 核心就两点

    1. 通过express中间件的参数长度来区分处理
    2. 改造express中间件的next方法
  • 相关阅读:
    ASP.NET 2.0 X64的奇怪问题
    【分享】从网上爬的WPF学习资料
    大家一起学习less 5:字符串插值
    大家一起学习less 3:命名空间
    我的模块加载系统 v18
    大家一起学习less 2:自带函数
    “计算机之子”的MVVM框架源码学习笔记
    我的MVVM框架 v0.1发布
    大家一起学习less 6:一些有用的混合函数
    less源码学习
  • 原文地址:https://www.cnblogs.com/cloud-/p/9829576.html
Copyright © 2020-2023  润新知