一分钟掌握Koa洋葱模型原理

1,143 阅读2分钟

一、开始

首先我们来看下面这段代码:

 const Koa = require("koa");
 const app = new Koa();
 app.use( (ctx, next) => {
   console.log(1);
    next();
   console.log(2);
 });
 app.use( (ctx, next) => {
   console.log(3);
    next();
   console.log(4);
 });
 app.use( (ctx, next) => {
   console.log(5);
    next();
   console.log(6);
 });
app.listen(3000);

按照正常的逻辑是输出是:1,2,3,4,5,6;但是根据koa的执行逻辑输出是:1,3,5,6,4,2;这种输出逻辑叫做洋葱模型(个人粗浅总结),下面我们就来实现实现这种输出逻辑。

二、实现

  1. 定义用来存函数的数组middlewares,定义用来将函数存入数组的函数use
const app = {
  middlewares: [],// 用来存函数的数组
  use: function (fn) {
    // 将app.use中传入的实参(函数)存入数组
    this.middlewares.push(fn);
  }
}
  1. 执行use函数,开始将use中的实参(函数)存入数组middlewares中
app.use((next) => {
  console.log(1);
  next();
  console.log(2);
});
app.use((next) => {
  console.log(3);
  next();
  console.log(4);
});
app.use((next) => {
  console.log(5);
  next();
  console.log(6);
});
  1. 递归执行数组中的函数
// 定义compose函数来递归执行middlwares中的函数,也可以定义其他函数名称,koa中定义的是compose,这里我们也定义compose函数
app.compose = function () {
   // 这里也可以不用返回一个函数,为了模拟koa的逻辑
  return function () {
    // 定义dispatch用来执行middlewares中的函数
    function dispatch(idx) {
      // 如果idx等于app.middlewares.length,则return掉
      if (idx === app.middlewares.length) {
        return;
      }
      // 从middlewares中取函数
      const fn = app.middlewares[idx];
      // 执行第一个app.use传入的实参(函数),并且传入实参next
      fn(function next() {
        // 在dispatch(1)中将会执行next中执行下一个app.use传入的实参(函数),开始递归
        dispatch(++idx);
      });
    }
    // 传入0,开始执行middlewares中的第一个函数,即执行app.use中传入的第一个函数
    dispatch(0);
  };
};
app.compose()();

三、总结

  1. next函数即下一个app.use中传入的函数;
  2. 第三个app.use的next函数,会因为idx等于app.middlewares.length直接return掉;
  3. 所以接下来会执行console.log(6);执行完console.log(6),即第二个app.use中的next函数已执行完,所以会往下执行则执行console.log(4);
  4. 当console.log(4)执行完,则表示第一个app.use中next函数已执行完;
  5. 所以会往下执行,执行console.log(2),执行完console.log(2),所有代码全部执行完成,完结撒花~

PS:本人承接Vue、React、Uniapp、小程序、RN等各种前端项目的外包,有外包业务的大佬欢迎来撩哦~【联系方式(微信):kaka_FE】