Express.js处理未捕获Node异常的最佳实践及优雅方案咨询
解决Express.js未捕获异常导致服务器崩溃的优雅方案
1. 配置全局错误处理中间件
Express原生支持全局错误处理机制,只需在所有路由和普通中间件之后定义一个带4个参数的中间件,就能捕获通过next(err)传递的错误。但要注意:异步路由/处理器内的异常不会被Express自动捕获,需要配合异步封装逻辑解决。
示例代码:
// 必须放在所有路由、中间件定义之后 app.use((err, req, res, next) => { console.error('服务器错误详情:', err.stack); // 区分开发/生产环境返回不同内容 const statusCode = err.statusCode || 500; res.status(statusCode).json({ message: process.env.NODE_ENV === 'production' ? '服务器内部错误' : err.message, error: process.env.NODE_ENV === 'production' ? {} : err.stack }); });
2. 封装异步路由处理器,自动捕获异常
不用每个路由都手动写try/catch或.catch(),写一个高阶函数统一处理异步函数的异常,自动将错误传递给next(err):
// 异步路由封装函数 const wrapAsync = (fn) => { return (req, res, next) => { // 自动捕获异步函数的异常并传给全局错误中间件 fn(req, res, next).catch(next); }; }; // 使用示例 app.get('/api/user', wrapAsync(async (req, res) => { // 这里的异步操作异常会被自动捕获 const user = await getUserById(req.params.id); res.json(user); }));
所有通过wrapAsync包裹的异步路由,内部异常都会被自动捕获,不会导致服务器崩溃。
3. 捕获全局未捕获异常与未处理Promise拒绝
针对路由外的异常(比如启动阶段错误、非路由逻辑的异常),需要监听Node.js的全局事件,但要注意:uncaughtException触发后Node.js状态可能不稳定,处理完建议优雅退出并通过进程管理器重启。
示例代码:
// 处理未捕获的同步异常 process.on('uncaughtException', (err) => { console.error('未捕获全局异常:', err); // 若有未完成的请求,尽量返回500后退出 process.exit(1); }); // 处理未处理的Promise拒绝 process.on('unhandledRejection', (reason, promise) => { console.error('未处理的Promise拒绝:', reason); process.exit(1); });
4. 用进程管理器实现自动重启
即使做了上述处理,部分严重错误仍可能导致服务器不稳定,使用PM2这类进程管理器可在崩溃时自动重启,保证服务可用性:
# 全局安装PM2 npm install pm2 -g # 启动Express应用 pm2 start app.js
PM2会自动监控进程状态,崩溃后立即重启,同时支持日志记录,方便后续排查问题。
内容的提问来源于stack exchange,提问作者blek__
相关产品推荐
相关产品推荐

