You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在ExpressJS中配置公共响应中间件并传递上下文参数

如何在Express中间件间传递上下文并统一处理响应

在Express里,你可以利用**res.locals**来安全地在中间件之间传递请求级别的上下文数据——它是每个请求独有的对象,专门用于存储请求生命周期内的共享数据,完全适配你这个场景。下面是结合需求优化后的具体实现方案:

1. 用res.locals传递上下文c

每个前置中间件只需要把生成的c挂载到res.locals上,然后调用next()让请求流走到公共响应中间件即可。不管是认证、业务接口还是404处理,都遵循这个逻辑:

function appSetup() { 
  const app = express() 
  // API token校验
  app.use((req, res, next) => { 
    let options = { requestId: req.get('X-Request-ID'), token: req.get('Authorization') } 
    let c = auth.authenticate(options) 
    // 将上下文挂载到res.locals
    res.locals.responseContext = c
    // 传递到下一个中间件(即公共响应中间件)
    next()
  }) 

  // 接口端点
  app.post('/books', async (req, res, next) => { 
    try {
      let c = await createBookService(req) // 异步操作必须加await
      res.locals.responseContext = c
      next()
    } catch (err) {
      // 捕获业务逻辑错误,构建错误上下文
      res.locals.responseContext = {
        check: false,
        code: 500,
        messageKey: 'error.book.create',
        requestId: req.get('X-Request-ID')
      }
      next()
    }
  }) 

  // 404 - 未找到
  app.use((req, res, next) => { 
    let c = mw.notfound(req) 
    res.locals.responseContext = c
    next()
  }) 

  // 公共响应对象中间件(最后执行,统一处理响应)
  app.use((req, res) => { 
    const ctx = res.locals.responseContext
    // 1. 设置自定义响应头
    res.setHeader('X-Custom-Header', 'your-custom-value')
    res.setHeader('X-Request-ID', ctx.requestId) // 传递请求ID便于追踪

    // 2. 处理多语言响应消息(假设已配置i18n模块)
    const message = req.i18n.__(ctx.messageKey) // 根据上下文里的key读取对应语言文案

    // 3. 构建统一格式的响应体
    const responseBody = {
      success: ctx.check,
      code: ctx.code,
      message: message,
      data: ctx.data || null // 业务数据(如创建后的书籍信息)
    }

    // 4. 发送最终响应
    res.status(ctx.code).send(responseBody)
  }) 

  return app 
}

2. 优化:封装上下文设置函数

如果每个中间件都重复写res.locals.responseContext = c; next(),可以封装一个工具函数简化代码:

function setResponseContext(res, ctx, next) {
  res.locals.responseContext = ctx
  next()
}

// 在中间件里调用示例:
app.use((req, res, next) => { 
  let options = { requestId: req.get('X-Request-ID'), token: req.get('Authorization') } 
  let c = auth.authenticate(options) 
  setResponseContext(res, c, next)
})

3. 异步中间件的注意事项

对于异步业务接口(比如createBookService),必须确保await异步操作完成后再设置上下文并调用next(),否则会出现上下文未生成就进入公共中间件的问题。同时要捕获异步错误,避免请求挂起。

4. 全局错误处理补充

如果需要统一捕获全局错误,可以在公共响应中间件前添加一个错误处理中间件(注意它必须包含4个参数):

// 全局错误处理中间件
app.use((err, req, res, next) => {
  res.locals.responseContext = {
    check: false,
    code: err.statusCode || 500,
    messageKey: 'error.server',
    requestId: req.get('X-Request-ID')
  }
  next() // 传递到公共响应中间件统一处理
})

这样不管是同步错误还是异步抛出的错误,都能被捕获并生成标准上下文,再交给公共中间件输出响应。

内容的提问来源于stack exchange,提问作者cogitoergosum

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:07:39