基础网络完全瘫痪时,应将try-catch作为错误观测出口,由独立retry逻辑处理重试决策、退避调度与异常过滤;仅对typeerror等可恢复异常重试,配合指数退避(带边界与抖动)和降级策略,避免裸重试与手动轮询。

基础网络完全瘫痪时,常规 await 会直接 reject 或抛出 NetworkError、TypeError(如 Failed to fetch)等底层异常,此时单纯靠 try-catch 捕获错误远远不够——它只做“兜底”,不提供恢复能力。真正实现自愈弹性,关键在于把 try-catch 作为**错误观测出口**,而把重试决策、延迟调度、退避计算交给独立的 retry 控制逻辑,两者分工明确:catch 不负责重试,只传递信号;retry 负责根据异常类型、次数和退避公式决定“何时再试”。
只对可恢复异常触发重试
网络完全中断时,浏览器或 Node.js 通常抛出 TypeError(fetch 失败)、NetworkError(低层连接异常)或特定 SDK 的超时类(如 Stripe 的 StripeConnectionError)。这些属于典型暂时性故障,应重试;而 SyntaxError(JSON 解析失败)、401/403(认证失效)等则不可恢复,必须立即终止。
- 在 retry 函数中用
shouldRetry(error)显式过滤:仅当error.name === 'TypeError' && /failed to fetch|network error/i.test(error.message)才继续 - 避免
catch (e) { retry() }这类无判断的裸重试,否则 404 或 CORS 错误也会被反复发起,浪费资源 - 若使用 Resilience4j/Guava/Retryer 工具,优先调用
retryIfExceptionOfType(TypeError.class),而非泛 catch Exception
指数退避必须带边界与抖动
网络全断期间,所有客户端若同时在 1s 后重试,极易形成请求洪峰,加剧拥塞。退避不是简单翻倍,而是要有上限、有扰动、有首次基线。
一款AI工具,主要用于产品经理技能,适用于 Claude Code、Codex、Cursor 和 Windsurf。涵盖 SaaS 指标诊断、PRD 评审、路线图规划、需求探索,以及面向产品经理的职业转型辅导等,适合需要提升相关任务效率的用户。
- 设基础延迟
baseDelay = 500ms,倍率multiplier = 2,最大延迟maxDelay = 10s,最多尝试maxAttempts = 5(含首次) - 第 n 次重试前等待:
delay = Math.min(maxDelay, baseDelay * Math.pow(multiplier, n - 1)) + Math.random() * 300(+0–300ms 抖动) - 例如:第1次等 500ms,第2次等 ~1000–1300ms,第3次 ~2000–2300ms……第5次卡在 10s 上限附近波动
await + try-catch 仅作执行壳,不掺杂控制流
业务代码里不要出现 while / setTimeout / 手动计数器。所有重试逻辑收口到统一 retry 函数,await 只负责“等一次结果”,try-catch 只负责“接住最终失败”。
- 正确写法:
const data = await retry(() => fetch('/api').then(r => r.json()), { shouldRetry, maxAttempts, ... }) - 错误写法:
let i = 0; while(i++ —— 堆栈丢失、抖动难加、失败统计缺失 - 每次 await 都应包裹在 retry 内部的 try/catch 中,确保
throw和Promise.reject()被统一捕获,原始错误堆栈不被吞
失败后提供降级与可观测出口
重试耗尽仍不可用,说明网络处于长时中断状态,此时需主动降级,而非静默失败。
- 配置
onFailure回调:记录日志(含重试次数、最后一次错误、当前退避延迟),上报监控系统 - 返回默认值或缓存数据(如
return cachedData ?? { status: 'offline', timestamp: Date.now() }) - 前端可触发 UI 提示:“网络不稳定,已自动重试 5 次,当前使用离线模式”










