Node.js中如何使用async/await正确拦截Promise错误
await调用异步函数的错误拦截方案
async/await是Promise的语法糖,所有异步执行中抛出的错误都会以Promise拒绝的形式传递,你可以用以下两种方式正确拦截:
1. try/catch 块包裹(推荐)
这是最通用的方案,只要是块内await调用抛出的错误,都会被catch块捕获,不管是请求报错、逻辑主动抛出的错误都能拿到。
基础调用示例:
try { const response = await myFunction(); // 所有正常逻辑写在try块内 console.log('调用成功', response); } catch (err) { // 错误统一在这里处理 console.error('调用出错:', err); }
针对你给出的Express路由场景,必须给所有await逻辑加try/catch,否则异步报错会触发未处理的Promise拒绝,导致请求挂起,甚至触发进程退出。改造后的路由代码如下:
import express from 'express'; import { helpers } from '../helpers.js'; const router = express.Router(); router.post('/createOrder', helpers.restAuthorize, async (req, res) => { try { // ... const orderId = await api.createOrder(); let order = { buyOrderId: orderId } const placed = await api.checkPlaced(orderId); if (placed) { let ack = await api.putAck(orderId); order.checksum = placed.checksum; order.ack = ack; } InternalOrder.create(order, (error, data) => { if (error) { return res.status(500).send({ message: error }); } else { res.json("ok"); } }) } catch (err) { // 捕获所有await链路的错误,统一返回响应 console.error('订单创建流程异常:', err); return res.status(500).send({ message: err.message || '服务内部错误' }); } }) export { router as exchangeRouter }
2. 链式catch捕获
如果是单步await调用,不想写try/catch块,可以直接在Promise后补catch回调,把错误和结果按数组形式返回,类似Go语言的错误处理风格:
const [err, response] = await myFunction() .then(res => [null, res]) .catch(err => [err, null]); if (err) { // 处理错误 console.error('调用失败', err); return; } // 正常逻辑处理response
额外优化建议
你写的myFunction存在多余的Promise包装,属于常见的Promise反模式:axios本身就返回Promise,async函数也会自动把返回值包装为Promise,不需要手动new Promise一层,简化后代码更简洁,错误也会自动沿链路抛出,不需要手动调用fail传递:
const myFunction = async () => { // ...前置逻辑 const response = await axios({ method: 'get', url: apiEndpoint, data: payload }); // ...处理响应逻辑 return orderId; }
如果你的Express项目有大量async路由,可以封装一个简单的高阶函数自动捕获错误,省得每个路由重复写try/catch:
// async路由包装器,自动捕获错误传给Express错误处理中间件 const asyncHandler = fn => (req, res, next) => { Promise.resolve(fn(req, res, next)).catch(next); }; // 使用时直接包裹路由处理函数即可 router.post('/createOrder', helpers.restAuthorize, asyncHandler(async (req, res) => { // 原有业务逻辑,不需要单独写try/catch const orderId = await api.createOrder(); // ...其余逻辑 }))
内容的提问来源于stack exchange,提问作者markzzz
相关产品推荐
相关产品推荐

