关于reduce实现koa-compose的问题

用reduce模拟实现koa中间件遇到的问题的先上代码

class Koa {
  constructor() {
    this.mids = [];
    this.ctx = {};
  }
  use(fn) {
    this.mids.push(fn);
  }

  // compose1(mids) {
  //   const dispatch = (i) => {
  //     if (i === mids.length) return Promise.resolve();
  //     let middleware = mids[i];
  //     console.log(middleware);
  //     return Promise.resolve(middleware(this.ctx, () => dispatch(i + 1)));
  //   };
  //   return dispatch(0);
  // }

  composeRight(middleWares) {
    return Promise.resolve(
      middleWares.reduceRight(
        (a, b) => {
          return () => Promise.resolve(b(this.ctx, a));
        },
        () => Promise.resolve()
      )
    );
  }

  composeLeft(middleWares) {
    return Promise.resolve(
      middleWares.reduce(
        (a, b) => {
          return () => Promise.resolve(a(this.ctx, b));
        },
        async (ctx, next) => {
          return await next();
        }
      )
    );
  }

  async send() {
    console.log("---------composeRight---------");
    const res2 = await this.composeRight(this.mids);
    await res2();
    console.log("---------composeLeft---------");
    const res3 = await this.composeLeft(this.mids);
    await res3();
  }
}
const app = new Koa();
app.use(async (context, next) => {
  console.log("第一个中间件 start");
  console.log(next);
  await next();
  console.log("第一个中间件 end");
});
app.use(async (context, next) => {
  console.log("第二个中间件 start");
  console.log(next);
  await next();
  console.log("第二个中间件 end");
});
app.use(async (context, next) => {
  console.log("第三个中间件 start");
  console.log(next);
  await next();
  console.log("第三个中间件 end");
});
app.use(async (context, next) => {
  console.log("第四个中间件 start");
  console.log(next);
  await next();
  console.log("第四个中间件 end");
});
app.send();

打印结果如下:
image.png
想请教一下为什么这里composeRight的时候可以正常执行但是composeLeft的的时候next为undifined 感觉绕不过来。。。

回复
阅读 397
1 个回答
新手上路,请多包涵

如果你在第一个中间件中打印 context,你会发现 context 也是 undefined。
这是因为你在执行第一个中间件的时候,并没有实际把参数传进去:

  composeLeft(middleWares) {
    return Promise.resolve(
      middleWares.reduce(
        (a, b) => {
          return () => Promise.resolve(a(this.ctx, b));
        },
        async (ctx, next) => { // a 的初始值为该函数
          return await next(); // 第一次执行 a 时,此时的 next 为第一个中间件
        }
      )
    );
  }
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏