Node.js如何无需try/catch自动返回错误响应?
Node.js 消除重复try/catch,自动捕获API异常方案
核心思路
通过包装异步路由处理函数 + 全局错误处理中间件的组合,实现自动捕获异常并返回500响应,完全替代每个接口里的重复try/catch代码。
1. 封装异步处理工具函数(适配Express 4及以下)
Express 4及更早版本不会自动捕获async/await函数的异常,所以需要写一个工具函数包装路由处理逻辑,自动捕获异常并传递给全局错误中间件:
// 定义async处理工具 const asyncHandler = (handler) => (req, res, next) => { Promise.resolve(handler(req, res, next)).catch(next); }; // 使用方式:用asyncHandler包裹你的异步路由函数 app.get('/api/user', asyncHandler(async (req, res) => { // 直接写业务逻辑,不用try/catch const user = await User.findById(req.params.id); res.status(200).json(user); }));
2. 全局错误处理中间件
不管是同步代码抛出的异常,还是通过next(err)传递的异步异常,都可以用这个中间件统一处理,返回500响应:
// 注意:这个中间件必须放在所有路由定义之后 app.use((err, req, res, next) => { // 可以先打印错误栈用于调试 console.error('服务器异常:', err.stack); // 返回统一的500错误响应 res.status(500).json({ code: 500, message: '服务器内部错误', // 生产环境可以隐藏具体错误信息,只在开发环境返回 detail: process.env.NODE_ENV === 'development' ? err.message : undefined }); });
3. Express 5+ 简化方案
Express 5版本开始会自动捕获async/await函数的异常,并自动调用next(err)传递给错误中间件,所以连包装函数都可以省:
// Express 5+ 直接写async路由函数 app.get('/api/user', async (req, res) => { const user = await User.findById(req.params.id); res.status(200).json(user); }); // 全局错误中间件依然保留,写法和上面一致 app.use((err, req, res, next) => { res.status(500).send('服务器出错了'); });
4. 模仿NestJS风格:直接返回数据自动响应
如果想和NestJS一样,不用手动调用res.send/res.json,直接返回业务数据即可,可以修改包装函数:
const asyncHandler = (handler) => async (req, res, next) => { try { // 直接获取路由函数的返回值 const result = await handler(req, res, next); // 自动返回200响应 res.status(200).json(result); } catch (err) { next(err); } }; // 使用时直接返回数据 app.get('/api/user', asyncHandler(async (req) => { return await User.findById(req.params.id); }));
注意事项
- 同步代码的异常:Express默认会自动捕获同步路由函数里的异常,无需额外处理。
- 异步回调中的异常:比如
setTimeout、fs.readFile这类老式回调API里的异常,需要手动捕获并调用next(err)传递给错误中间件。 - 错误中间件必须包含4个参数(
err, req, res, next),哪怕next用不到也要写上,否则Express会把它当成普通中间件,不会处理异常。
内容的提问来源于stack exchange,提问作者Code Guru
相关产品推荐
相关产品推荐

