koa-compose原理

65 阅读1分钟

koa-compose是js中compose思想的实践,这种组合思想使单个函数可以聚焦自己的逻辑,将多个这样的完成自己简单逻辑的函数组合在一起共同形成复杂的逻辑

koa-compose将中间件形成我们常说的“洋葱模型”

image.png

function compose(middleWare) {
  // 校验传入的参数是数组,校验数组中每一项是函数
  if (!Array.isArray(middleWare)) throw new TypeError('Middleware stack must be an array!')
  for (const fn of middleWare) {
    if (typeof fn !== 'function') throw new TypeError('Middleware must be composed of functions!')
  }
  return function (context, next) {


    //index用于防止在一个中间件函数中多次调用next()
    //如果多次调用了next(),则index >= i
    let index = -1;

    function dispatch(i) {

      if (i <= index) return Promise.reject(new Error('next() called multiple times'));
      index = i

      let fn = middleWare[i];
      if (i === middleWare.length) {
        fn = next;
      }
      // 最后一个中间件中有调用next函数,则返回Promise.resolve。如果没有,则不执行next函数, 直接返回 Promise.resolve()
      if (!fn) return Promise.resolve()
      try {
        //这里将下一个中间件放入本次中间件的第二个参数中
        return Promise.resolve(fn(context, dispatch.bind(null, i + 1)))
      } catch (err) {
        return Promise.reject(err)
      }
    }

    return dispatch(0);
  }
}

调用方法如下:


async function middileware1(ctx, next) {
  console.log('11111');
  await next();
  console.log('55555');
}

async function middileware2(ctx, next) {

  console.log('2222');
  await next();
  console.log('4444');
}

async function middileware3(ctx, next) {
  console.log('33333');

  next()
}

const a = compose([middileware1, middileware2, middileware3])({}, res => {
  console.log(res, 'nextnext');
}).then(res => {
  console.log(res, 'jjjj');
})