一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

async await 怎样在异步操作中注入异常

时间:2026-07-15 20:40:54 编辑:袖梨 来源:一聚教程网

async/await本身不提供异常注入能力,它只是消费Promise的语法糖;真正的异常注入需在await前主动throw、封装异步调用重抛增强错误、或在Promise中reject自定义Error实例,并避免未await、静默吞错、上下文污染等陷阱。

async/await 本身不提供“异常注入”能力——它只是语法糖,用于更清晰地消费 Promise。所谓“异常注入”,实际是指在异步流程中主动触发、构造并传递错误,使其能被上层 try/catch 捕获,同时携带上下文信息(如 traceId、操作名、参数等),而非简单抛出原始错误。

在 await 前主动 throw 错误

最直接的方式是在 await 表达式执行前,根据业务条件提前抛出错误,让控制流进入 catch 分支:

  • 适用于参数校验、权限检查、前置状态判断等场景
  • 错误会立即被外层 try/catch 捕获,stack trace 清晰指向当前函数位置
  • 示例:if (!userId) throw new Error('Missing userId');

封装异步调用并重抛增强型错误

避免裸写 await fetch()await db.query(),统一用工具函数包装,在 catch 中构造带上下文的错误对象:

  • 保留原始 error.stack,并附加当前层信息(如 URL、SQL、traceId)
  • 推荐使用自定义错误类(如 AppError),含 codecontextcause 字段
  • 示例:throw new AppError('DB_TIMEOUT', { sql, traceId }, originalErr);

在 Promise 构造器中 reject 自定义错误

当手动创建 Promise(如封装回调 API、定时器、事件监听)时,可在 reject 时传入结构化错误:

  • 确保 Promise 被 await 后,该 reject 能被 try/catch 正确捕获
  • 不要忽略 reject 的值类型——建议传 Error 实例,而非字符串
  • 示例:reject(new AppError('TIMEOUT', { timeout: 5000 }));

避免常见陷阱

以下做法会导致异常“消失”或无法溯源:

  • 调用 async 函数但未 await,也未接 .catch() → 异常变成 unhandled rejection
  • 在 catch 中只 console.error 却不 re-throw 或返回 fallback → 错误被静默吞掉
  • 用全局变量存 traceId 或 error 上下文 → 多请求并发时发生污染
  • 拼接 stack 时丢弃原始 error.cause 或未保留 new Error().stack → 调用链断裂

热门栏目