You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 14:06:30