async 封装本身不自动提供异常保护,但可通过结构化设计实现集中可靠错误处理:统一收口错误边界、显式划分错误范围、嵌入重试降级逻辑、避免中间层吞错、并行用 allSettled、递归逐层防护、finally 清理资源、结合 Result 类型将错误建模为数据。
async 封装本身不自动提供异常保护,但能通过结构化设计让错误捕获更集中、更可靠。关键不是靠语法糖兜底,而是利用 async/await 的执行流特性,把错误边界显式划清楚、把重试和降级逻辑自然嵌入流程中。
用 async 函数统一收口错误边界
把原始异步操作(如 fetch、数据库查询)包裹进一个 async 函数,所有校验和异常处理都在这个函数内部完成,外部只面对一个“可能失败”的 Promise:
- HTTP 状态检查、JSON 解析、业务 code 判断都放在 try 块里,避免调用方重复写这些逻辑
- catch 中统一做日志、上报、UI 提示,再选择 re-throw 或返回 fallback 值
- 不直接传 Promise,而是传 promiseFn —— 防止调用时立即执行却未被 try 包裹
在链式调用中保持错误可传递
多个 await 串行时,每个 await 后的代码都属于前一个 Promise 的 then 分支,错误会自然沿链向上冒泡。但要注意:
- 避免在中间层吞掉错误却不 re-throw,否则下游无法感知失败
- 需要降级时,可用 Promise.resolve(fallback) 替代 throw,让流程继续而非中断
- 并行请求用 asyncio.gather(..., return_exceptions=True)(Python)或 Promise.allSettled()(JS),避免单点失败阻断全部
对递归或循环类异步操作做逐层防护
异步递归(如重试、轮询)容易因漏包导致错误逸出。正确做法是:
- 每次递归调用都发生在 try-catch 内部,而不是只包最外层
- catch 中判断是否重试,满足条件后 await 等待再发起下一轮,确保新调用仍在保护范围内
- finally 里清理资源(如清除定时器、释放锁),防止因异常跳过清理逻辑
结合 Result 类型提前隔离错误语义
像 Flutter 的 async_result 或 Rust 的 Result 这类模式,把成功与失败都建模为数据类型,而不是依赖 throw/catch:
- 网络超时、解析失败、业务码非 0 都转为对应 Failure 子类型,不再触发异常
- 后续逻辑用 .onSuccess() / .onFailure() 分支处理,避免 try-catch 嵌套
- 错误变成可组合、可映射、可记录的数据,更适合端侧稳定性和可观测性要求