You need to enable JavaScript to run this app. 如何在Promise内部正确抛出异常?抛出异常后仍触发then成功回调的原因及解决方法
优惠活动
大模型
产品
解决方案
定价
更多

如何在Promise内部正确抛出异常?抛出异常后仍触发then成功回调的原因及解决方法

Promise异常传递问题修正

异常行为的根本原因

当前代码抛出异常后会走入.then()的成功回调分支,是两个逻辑问题叠加导致的:

  • 链尾catch直接吞掉了所有失败状态
    你在new Promise(...)的结果后链式绑定了.catch((e) => console.log(e)),按照Promise的执行规则:这个catch会捕获链上游所有throw、reject产生的错误,同时把catch回调的返回值(也就是console.log的返回值undefined)作为新的成功状态的值,传递给后续的.then()调用。
    也就是说,不管你在Promise内部是主动reject还是throw错误,只要被这个catch捕获,最终返回给调用方的Promise就会从“失败状态”被反转成“成功状态,值为undefined”,自然会触发then的第一个成功回调。
  • 内部逻辑没有做分支阻断
    原代码在if (found) resolve(found);之后没有加执行流阻断,虽然Promise的状态一旦敲定就不会被后续调用的reject修改,但这种无阻断的写法很容易在后续迭代中引入逻辑隐患。

正确在Promise内部处理异常的实现方式

要让错误能正常传递给调用方的then错误回调,核心原则是不要用catch抹平所有失败状态,同时梳理清楚各分支的状态流转:

  1. 明确各场景的Promise状态:
    • 扫描响应校验不通过:直接调用reject()传递标准化错误,不依赖throw的隐式行为,执行后立刻阻断后续逻辑
    • 匹配到访客:调用resolve()传递访客对象,执行后阻断后续逻辑
    • 未匹配到访客:调用reject()传递原始扫描响应
  2. 保留错误日志的同时不破坏状态传递:如果需要在函数内部统一捕获错误打日志,要在catch回调里重新抛出捕获到的错误,保证Promise能保持原有的失败状态,正常传递给调用方。

修正后的代码

export const handleScanResponse = (
  scanResponse: IScanResponse,
  visitors: IVisitor[]
): Promise<IVisitor | any> => {
  return new Promise((resolve, reject) => {
    // 扫描响应校验失败场景
    if (!scanResponse || scanResponse.errorDesc !== "SUCCESS") {
      reject(new Error("Scan response is invalid!"));
      return;
    }

    // 匹配访客逻辑
    const found = visitors.find((p: IVisitor) => {
      if ("qrcode" in scanResponse) {
        return p.code?.toLowerCase() === scanResponse.qrcode.toLowerCase();
      }
      return p.document_number && scanResponse.document_number
        ? p.document_number.toLowerCase() === scanResponse.document_number.toLowerCase()
        : false;
    });

    // 匹配成功场景
    if (found) {
      resolve(found);
      return;
    }

    // 匹配失败场景
    reject(scanResponse);
  })
  // 统一捕获错误打日志,同时不吞掉失败状态
  .catch((e) => {
    console.log(e);
    // 重新抛出错误,保证Promise保持失败状态向上传递
    throw e;
  });
};

修正完成后,原有的调用逻辑就能正常触发对应分支:

  • 匹配到访客时:执行this.visitorWasFound(foundVisitor)
  • 匹配失败、扫描响应无效、内部运行异常时:执行this.visitorNotFound(scanResponse)

内容的提问来源于stack exchange,提问作者user14451004

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.09 05:27:03