优雅应对多种错误类型的关键在于统一错误分类与提前隔离失败路径:封装每个 await 为返回 {data, error} 的独立函数,或用 promise.allsettled 处理并行请求,再按 error 类型精准识别与聚合反馈。

用一个 try-catch 包住多个 await 调用,本身是可行的,但“优雅应对多种错误类型”关键不在 catch 里做一堆 instanceof 判断,而在于统一错误分类 + 提前隔离失败路径。
把每个 await 封装成“可失败”的独立函数
不要直接 await 多个接口,而是为每个请求写一个带错误兜底的小函数,返回 { data, error } 形式的结果。这样 try-catch 不用管具体哪个失败,逻辑更清晰。
- 例如封装 fetchUser() → 返回 { user: ..., error: null } 或 { user: null, error: 'network' }
- 所有 await 都变成 const { data: user, error: userErr } = await fetchUser()
- 后续根据 userErr 做分支处理,而不是在 catch 里靠 error.name 或 message 字符串匹配
用 Promise.allSettled 配合结构化结果
如果多个接口无依赖、可并行,优先用 allSettled。它不会抛错,每个结果自带 status: 'fulfilled' | 'rejected',天然支持多类型错误归类。
- const results = await Promise.allSettled([api1(), api2(), api3()])
- 遍历 results,对每个 result.status === 'rejected' 的,取 result.reason(即原始 error)做类型判断
- 比如 reason instanceof TypeError → 网络问题;reason?.status === 401 → 登录过期;直接统一处理,不打断其他请求
在 catch 中按 error 构造器或 symbol 做精准识别
如果必须用单个 try-catch(比如接口有执行顺序依赖),就在 throw 时主动构造带类型的 Error 子类,catch 里用 constructor 判断,比字符串匹配更可靠。
- 定义 class ApiTimeoutError extends Error { constructor(msg) { super(msg); this.type = 'timeout'; } }
- 接口层主动 throw new ApiTimeoutError('user api timeout')
- catch (err) { if (err instanceof ApiTimeoutError) { /* 重试 */ } else if (err instanceof ValidationError) { /* 提示表单 */ } }
错误聚合后统一决策,而非逐个响应
多个接口失败时,用户不需要看到 3 条“请求失败”,而是需要一句明确反馈:“用户信息加载成功,但订单和地址未同步,请稍后刷新”。这需要在 catch 后做状态汇总。
- 维护一个 errors = { user: null, order: null, address: null }
- 每个 await 后捕获局部 error 并存入对应字段(不用 throw)
- 全部 await 完再检查 errors:全空 → 成功;部分有值 → 按业务规则生成友好提示
本质不是让 try-catch 更“聪明”,而是减少它要承担的判断责任——把错误识别前移到调用点,把错误语义显式化,把恢复策略从业务层下沉到工具层。











