模仿express和koa中间件原理

expresskoa的中间件区别就在与express的中间件里,next函数前不能加 await,因为next函数是个同步函数,没有返回promise,所以如果使用了await,那么就会导致所期望的异步代码执行顺序和想象的不一样,而koanext(也就是dispatch)包裹了一层Promise.resolve,await后就能保证即使有异步操作,洋葱模型也能正常执行.
简单写下大致思路

class App {
  constructor() {
    this.middleWare = [];
  }

  use(name, ...middleWares) {
    middleWares.forEach((fn) => {
      const handler = {
        key: name,
        handler: fn,
      };
      this.middleWare.push(handler);
    });
  }

  run(name) {
    let index = 0;

    // 获取下个符合条件的中间件
    const getValidMiddle = () => {
      if (index >= this.middleWare.length) return null;
      const { key, handler } = this.middleWare[index++];
      if (key == name || key == "*") {
        return handler;
      } else {
        return getValidMiddle();
      }
    };

    // next 函数,中间件函数包裹一层, next函数是同步函数,所以 await next()并不会等待中间件的返回结果
    // function next() {
    //   const handler = getValidMiddle();
    //   if (handler) {
    //     handler.call(null, { index: `第${index}个中间件` }, next);
    //   }
    // }
    // 改造成 返回 promise.resolve的函数,就可以解决
    function next() {
      const handler = getValidMiddle();
      if (handler) {
        return Promise.resolve(
          handler.call(null, { index: `${index}个中间件` }, next)
        );
      }
      return Promise.resolve();
    }

    next();
  }
}
const app = new App();

app.use("test", m1, m2);
app.use("test", m3, m4);

app.run("test");

async function m1(args, next) {
  console.log("中间件1 开始,参数:>>>");
  next && (await next());
  console.log("中间件1 结束");
}
async function m2(args, next) {
  console.log("中间件2 开始,参数:>>>");
  next && (await next());
  console.log("中间件2 结束");
}
async function m3(args, next) {
  await sleep(2000);
  console.log("中间件3 开始,参数:>>>");
  next && next();
  console.log("中间件3 结束");
}
function m4(args, next) {
  console.log("中间件4 开始,参数:>>>");
  next && next();
  console.log("中间件4 结束");
}

function sleep(time) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve();
    }, time);
  });
}

你可能感兴趣的:(express,中间件)