侧边栏壁纸
博主头像
colo

欲买桂花同载酒

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

实现一个支持异步中间件的简易Node.js框架核心

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

题目

实现一个支持异步中间件的简易Node.js框架核心

信息

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

考点

中间件机制,异步流程控制,错误处理

快速回答

实现要点:

  • 创建Application类管理中间件队列
  • 通过use()方法注册中间件,支持异步函数
  • 实现handleRequest()方法按顺序执行中间件
  • 使用next()机制控制流程传递
  • 添加错误处理中间件支持(函数参数为4个)
## 解析

原理说明

Node.js框架(如Express/Koa)的核心是中间件管道机制:

  • 中间件是按顺序执行的函数,接收请求/响应对象和next回调
  • 每个中间件通过调用next()将控制权移交下一个中间件
  • 异步中间件需返回Promise或使用async/await
  • 错误处理中间件有4个参数(err, req, res, next)

代码实现

class Application {
  constructor() {
    this.middleware = [];
  }

  // 注册中间件
  use(fn) {
    if (typeof fn !== 'function') {
      throw new TypeError('Middleware must be a function!');
    }
    this.middleware.push(fn);
  }

  // 请求处理入口
  handleRequest(req, res) {
    const ctx = { req, res };
    const dispatch = (i) => {
      if (i >= this.middleware.length) return Promise.resolve();

      const fn = this.middleware[i];
      try {
        // 执行中间件并处理异步
        return Promise.resolve(fn(ctx, () => dispatch(i + 1)));
      } catch (err) {
        return Promise.reject(err);
      }
    };

    return dispatch(0).catch(err => {
      // 触发错误处理
      const errorHandler = this.middleware.find(fn => fn.length === 4);
      errorHandler?.(err, ctx.req, ctx.res, () => {});
    });
  }
}

// 使用示例
const app = new Application();

// 普通中间件
app.use(async (ctx, next) => {
  console.log('Middleware 1 start');
  await next();  // 移交控制权
  console.log('Middleware 1 end');
});

// 错误处理中间件(4个参数)
app.use((err, req, res, next) => {
  console.error('Error:', err);
  res.statusCode = 500;
  res.end('Internal Server Error');
});

// 模拟请求
app.handleRequest({}, { end: () => {} });

最佳实践

  • 使用Promise.resolve包装中间件返回值,统一处理同步/异步函数
  • 通过fn.length判断错误处理中间件(参数数量为4)
  • 创建上下文对象ctx封装req/res,避免污染原生对象
  • next()调用处添加try/catch捕获同步错误

常见错误

  • 忘记调用next()导致请求挂起
  • 未正确处理异步错误(需用Promise.catch
  • 多次调用next()引发重复执行
  • 错误处理中间件未放在最后(应作为最终兜底)

扩展知识

  • Koa对比:Koa使用async/await替代回调,通过ctx.onerror集中处理错误
  • 性能优化:使用组合函数(compose)减少递归开销
  • 洋葱模型:中间件执行顺序类似洋葱,先入后出(请求→响应方向)
  • 实际应用:Express的router和Koa的koa-compose都是该模式的工业级实现