先看一个例子

app.use(async (ctx, next) => {
  console.log('---> 中间件1 before');
  await next();
  console.log('---> 中间件1 after');
});


app.use(async (ctx, next) => {
  console.log('---> 中间件2 before');
  await next();
  console.log('---> 中间件2 after');
});


app.use(async (ctx, next) => {
  console.log('---> 中间件3 before');
  await next();
  console.log('---> 中间件3 after');
});

输出结果

---> 中间件1 before
---> 中间件2 before
---> 中间件3 before
---> 中间件3 after
---> 中间件2 after
---> 中间件1 after

koa中间件会被next分成两部,上半部分会先执行,下半部分会在中间件执行完之后再执行

app.use中传入的异步函数及中间件,app.use是注册中间件的过程,use的过程会将中间件函数push进入,koa的中间件队列上面的中间件过程注册完之后,就如下面的样子维护在中间件队列中:

const middleWears = [
  async (ctx, next) => {
    console.log('---> 中间件1 before');
    await next();
    console.log('---> 中间件1 after');
  },
  async (ctx, next) => {
    console.log('---> 中间件2 before');
    await next();
    console.log('---> 中间件2 after');
  },
  async (ctx, next) => {
    console.log('---> 中间件3 before');
    await next();
    console.log('---> 中间件3 after');
  }
];

那么中间件是如何执行的?

中间件的执行是在koa的app.listen中,中间件执行是通过一个compose函数实现的,接下来我们实现一个简易的compose函数来查看中间件的执行过程:

function compose(middleWears) {
  return function (ctx) {
    const dispatch = (i) => {
      const fn = middleWears[i];
      if (fn) {
        return fn(ctx, () => dispatch(i + 1));
      }
    };
    dispatch(0);
  };
};

可以看出其实中间件的next函数,就是包装之后的dispatch,包装之后的dispath 会调用中间件函数,中间件函数再执行next(也就是其中会执行中间件的dispatch函数),就形成中间件的雏形,也就是形成了中间件的特性,不掉用next就不会执行下一个中间件


H_H_code
51 声望3 粉丝