题目
Express中间件执行顺序与错误处理
信息
- 类型:问答
- 难度:⭐⭐
考点
中间件执行原理,错误处理机制,中间件栈
快速回答
关键要点:
- 中间件按声明顺序执行,需调用
next()传递控制权 - 错误处理中间件需4个参数
(err, req, res, next) - 同步错误自动捕获,异步错误需手动传递
- 路由处理结束后需终止响应或调用
next()
1. 中间件执行原理
Express中间件本质是函数队列,按声明顺序组成中间件栈。请求进入时:
- 依次执行匹配的中间件
- 每个中间件通过
next()将控制权移交下一个 - 若未调用
next(),请求会挂起
// 示例:基础中间件栈
app.use((req, res, next) => {
console.log('Middleware 1');
next(); // 必须调用
});
app.get('/api', (req, res, next) => {
console.log('Route handler');
next();
});2. 错误处理机制
Express通过特殊签名识别错误处理中间件:
- 必须声明4个参数:
(err, req, res, next) - 通常放在所有中间件之后
- 同步错误自动捕获,异步错误需主动传递
// 同步错误示例
app.use((req, res, next) => {
throw new Error('Sync error'); // 自动被错误处理中间件捕获
});
// 异步错误处理
app.get('/async', async (req, res, next) => {
try {
await fetchData();
} catch (err) {
next(err); // 必须手动传递
}
});
// 错误处理中间件(放在最后)
app.use((err, req, res, next) => {
res.status(500).json({ error: err.message });
});3. 最佳实践
- 顺序原则:通用中间件在前,路由中间件在后,错误处理在末尾
- 响应终止:路由处理结束必须
res.send()或res.end() - 异步安全:Promise/async函数内使用
try/catch - 错误分类:根据错误类型返回不同HTTP状态码
4. 常见错误
- 错误1:忘记调用
next()导致请求卡死 - 错误2:异步操作未捕获异常(如未在Promise中
catch) - 错误3:将错误处理中间件放在路由之前
- 错误4:多次调用
res.send()触发"Can't set headers"错误
5. 扩展知识
- 洋葱模型:中间件执行类似洋葱,先进入的中间件后退出(响应阶段逆序)
- 第三方中间件:
morgan(日志)、helmet(安全)、cors(跨域) - 路由级中间件:
app.use('/path', middleware)实现路径过滤 - 性能优化:避免在中间件中阻塞操作,善用流式处理