侧边栏壁纸
博主头像
colo

欲买桂花同载酒

  • 累计撰写 1823 篇文章
  • 累计收到 0 条评论

实现一个简单的中间件系统

2025-12-6 / 0 评论 / 4 阅读

题目

实现一个简单的中间件系统

信息

  • 类型:问答
  • 难度:⭐⭐

考点

中间件原理,洋葱模型,异步流程控制

快速回答

实现一个中间件系统的核心要点:

  • 使用use()方法注册中间件函数
  • 通过next()控制执行流程
  • 采用洋葱模型(先进后出)的执行顺序
  • 使用递归或Promise处理异步
## 解析

1. 中间件核心原理

中间件本质是函数队列,通过next控制执行流。典型执行顺序:

// 洋葱模型执行顺序
→ Middleware1 前置
  → Middleware2 前置
    → 核心逻辑
  ← Middleware2 后置
← Middleware1 后置

2. 代码实现示例

基础实现(同步):

class MiddlewareSystem {
  constructor() {
    this.middlewares = [];
  }

  use(fn) {
    this.middlewares.push(fn);
  }

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

// 使用示例
const app = new MiddlewareSystem();
app.use((ctx, next) => {
  console.log('Middleware 1 start');
  next();
  console.log('Middleware 1 end');
});
app.run();

支持异步(Promise):

class AsyncMiddlewareSystem {
  constructor() {
    this.middlewares = [];
  }

  use(fn) {
    this.middlewares.push(fn);
  }

  run() {
    const dispatch = (i) => {
      if (i >= this.middlewares.length) return Promise.resolve();
      const middleware = this.middlewares[i];
      return Promise.resolve(middleware({}, () => dispatch(i + 1)));
    };
    return dispatch(0);
  }
}

3. 最佳实践

  • 错误处理:添加catch捕获异常
    app.use(async (ctx, next) => {
      try {
        await next();
      } catch (err) {
        console.error(err);
      }
    });
  • 上下文传递:通过ctx对象共享数据
  • 提前终止:不调用next()可中断执行流

4. 常见错误

  • 忘记调用next():导致后续中间件不执行
  • 多次调用next():引发不可预测行为
  • 异步未处理:未返回Promise导致执行顺序错乱
  • 未处理错误:异步错误未捕获导致进程崩溃

5. 扩展知识

  • Koa中间件原理:基于koa-compose的递归Promise链
  • Express与Koa区别:Express基于回调(非纯洋葱),Koa基于Promise
  • 性能优化:使用while循环替代递归减少调用栈深度
  • 实际应用:路由、日志、鉴权、数据校验等场景