实现执行中间件的函数

javascript/exercises/middlewares2026-08-24 19:46:25

middleware 函数是一个具有 next 参数的函数,middleware 函数内会在某个地方调用 next 函数以执行下一个 middleware 函数,此 middleware 函数不会停止执行,而是在下一个 middleware 函数返回后继续执行剩余代码,例如:

function middleware1(next) {
  console.log("1 start")
  next()
  console.log("1 end")
}

function middleware2(next) {
  console.log("2 start")
  next()
  console.log("2 end")
}

function middleware3(next) {
  console.log("3 start")
  next()
  console.log("3 end")
}

实现一个 compose 函数,它接受一个 middleware 函数数组 middlewares,并返回一个函数,返回的函数会从第一个 middleware 函数开始执行这些 middleware 函数。

例如:

compose([middleware1, middleware2, middleware3])()

将输出:

1 start
2 start
3 start
3 end
2 end
1 end

递归方式

function compose(middlewares) {
  return function() {
    function dispatch(i) {
      if (i >= middlewares.length) return;
      const middleware = middlewares[i];
      middleware(() => dispatch(i + 1));
    }
    dispatch(0);
  }
}

递归方式比较容易想到,但是如果 middlewares 数组非常长,递归调用可能会导致调用栈溢出,例如以如下方式调用时:

function createMiddleware(i) {
  return function (next) {
    console.log(i + " start");
    next();
    console.log(i + " end");
  };
}

const middlewares = [];

for (let i = 1; i <= 4000; i++) {
  middlewares.push(createMiddleware(i));
}

compose(middlewares)();

解决调用栈溢出问题

我不会。

如果用循环来执行不能使 next() 之后的代码在下一个中间件执行完毕后继续执行,而是会在下一个中间件执行前执行,即输出变成:

1 start
1 end
2 start
2 end
3 start
3 end

使用异步操作也是同样的问题。

可能可以的考虑的方法:生成器函数(可以暂停的函数),或者将 next() 前后的代码拆分成两个部分,但是实现起来不太可能。

所以这题有没有解?

本页目录