谈谈Koa 中的next

论坛 期权论坛 编程之家     
选择匿名的用户   2021-6-2 15:51   1795   0

前言

最近在试着把自己写的 koa-vuessr-middleware 应用在旧项目中时,因为旧项目Koa 版本为1.2,对中间件的支持不一致,在转化之后好奇地读了一下源码,整理了一下对Koa 中next 在两个版本中的意义及相互转换的理解


正文

1.x 中的next

从Koa 的 application.js 中找到中间件部分的代码,可以看出,use 传入的中间件被放入一个middleware 缓存队列中,这个队列会经由 koa-compose 进行串联

app.use = function(fn){
  // ...
  this.middleware.push(fn);
  return this;
};
// ...
app.callback = function(){
  // ...
  var fn = this.experimental
    ? compose_es7(this.middleware)
    : co.wrap(compose(this.middleware));
  // ...
};
复制代码

而进入到koa-compose 中,可以看到compose 的实现很有意思(无论是在1.x 还是在2.x 中,2.x 可以看下面的)

function compose(middleware){
  return function *(next){
    if (!next) next = noop();

    var i = middleware.length;

    while (i--) {
      next = middleware[i].call(this, next);
    }

    return yield *next;
  }
}
// 返回一个generator 函数
function *noop(){}
复制代码

从代码中可以看出来,其实next 本身就是一个generator, 然后在递减的过程中,实现了中间件的先进后出。换句话说,就是中间件会从最后一个开始,一直往前执行,而后一个中间件得到generator对象(即next)会作为参数传给前一个中间件,而最后一个中间件的参数next 是由noop 函数生成的一个generator

但是如果在generator 函数内部去调用另一个generator函数,默认情况下是没有效果的,compose 用了一个yield * 表达式,关于yield *,可以看看 阮一峰老师的讲解;


2.x 中的next

Koa 到了2.x,代码越发精简了,基本的思想还是一样的,依然是缓存中间件并使用compose 进行串联,只是中间件参数从一个next 变成了(ctx, next),且中间件再不是generator函数而是一个 async/await 函数了

  use(fn) {
    // ...
    this.middleware.push(fn);
    return this;
  }
  // ...
  callback() {
    const fn = compose(this.middleware);
    // ..
  }
复制代码

同时, compose 的实现也变了,相较于1.x 显得复杂了一些,用了四层return,将关注点放在dispatch 函数上:

function compose (middleware) {
  return function (context, next) {
    // last callevFSNiX{[z
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP