async/await 本身不提供跨模块错误处理能力,需通过 to 函数统一解构 promise、api 层拦截标准化错误、高阶函数封装重试/降级/超时策略,并在顶层设置兜底捕获机制。

async/await 本身不提供跨模块的错误处理能力,关键在于把错误处理逻辑抽象出来、统一导出、按需注入,而不是让每个模块重复写 try/catch 或忽略错误传播路径。
用 to 函数统一解构 Promise 结果
定义一个轻量工具函数,把 Promise 转为 [error, data] 元组,避免每个模块都写 try/catch:
export function to(promise) {
return promise
.then(data => [null, data])
.catch(error => [error, null]);
}
在业务模块中直接解构使用,错误判断更直观:
import { to } from './utils/async';
async function loadUser(id) {
const [err, user] = await to(fetch(`/api/users/${id}`).then(r => r.json()));
if (err) {
console.warn('用户加载失败', err.message);
return null;
}
return user;
}
在 API 客户端层统一拦截和标准化错误
把错误处理提前到请求发起环节,下游模块只关注“成功拿到什么”,不操心“失败怎么办”:
- 封装 fetch 或 axios 实例,在响应拦截器里检查 status、解析错误体、抛出语义化错误类(如
ApiNetworkError、ApiAuthError) - 所有业务调用方只需处理业务逻辑,异常由上层统一日志、上报或降级
- 例如:401 自动跳登录页,503 返回兜底数据,网络超时触发重试
用高阶函数包装可复用的错误策略
针对不同场景,把重试、降级、超时等逻辑封装成函数,按需组合:
-
withRetry(fn, { times: 3, delay: 500 })—— 失败自动重试 -
withFallback(fn, fallbackValue)—— 异常时返回默认值 -
withTimeout(fn, 8000)—— 超时后拒绝 Promise
这些函数返回新的 async 函数,可在任意模块导入使用,保持调用侧代码干净。
顶层必须有兜底错误捕获机制
模块间流转再规范,也防不住漏掉 await 或顶层异步回调没处理。因此:
- Node.js 环境监听
process.on('unhandledRejection'),记录并告警 - 前端框架(如 React)在根组件或路由层用 Error Boundary +
useEffect监听全局 Promise 拒绝 - Express/Koa 中间件统一捕获 async handler 抛出的错误,避免进程崩溃











