如何在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
相关产品推荐
相关产品推荐

