基础网关瘫痪时,await 无法自动降级或重试,需通过 try-catch 封装可重试函数,结合指数退避、清晰降级路径及可观测性记录,实现“等得明白、退得从容、兜得住底”的优雅处理。

当基础网关完全瘫痪时,await 本身无法自动降级或重试——它只是等待 Promise 完成。真正起作用的是你如何封装这个 await 调用:用 try-catch 捕获失败,并在 catch 中触发带退避策略的重试或降级逻辑,才能实现“优雅”。关键不在 try-catch 本身,而在它和退避算法、降级兜底的协同设计。
用 try-catch 封装可重试的 await 调用
不要让业务代码直接 await 网关请求;而是封装成一个可重试的异步函数,内部用 try-catch 控制流程。每次失败都进入 catch,由你决定是重试、降级,还是抛出最终错误。
- 把网关调用包装进独立函数(如
callGateway()),并在其外层套一层重试控制器 - catch 中不直接 throw,而是根据失败次数、错误类型(如 503、超时、网络异常)决定后续动作
- 避免在顶层 await 外裸写 try-catch —— 那样只能捕获一次,无法实现“多次尝试 + 退避”
集成指数退避(Exponential Backoff)控制重试节奏
连续快速重试雪崩式失败的网关只会加重压力。退避算法让每次重试间隔逐渐拉长,给系统恢复留出窗口。
- 从 100ms 开始,每次失败后乘以 2(如 100 → 200 → 400 → 800ms),并加入随机抖动(±20%)防同步冲击
- 设置最大重试次数(如 3 次)和最大退避上限(如 1.6s),避免无限等待
- 可在 catch 块中用
await new Promise(r => setTimeout(r, delay))实现暂停,再递归或循环重试
定义清晰的降级路径作为最终兜底
当重试耗尽仍失败,必须有确定的降级行为,而非让用户卡在 loading 或收到 500。降级不等于“返回空”,而是提供有业务意义的替代响应。
- 返回缓存数据(本地内存缓存、localStorage 中的旧结果,标注“已过期”)
- 切换到备用网关或轻量 API(如只查用户基础信息,跳过风控/计费等强依赖模块)
- 返回预设的静态 fallback 响应(如 { code: 200, data: {}, message: "服务暂不可用,功能已简化" })
记录可观测性信息辅助决策与复盘
优雅降级不只是“不报错”,还要让人知道发生了什么。每一次重试、降级、超时,都应留下可追溯痕迹。
- 在 catch 中打点日志,包含原始错误、重试次数、退避时长、是否触发降级
- 上报指标(如 gateway_failures_total、fallback_triggered_count),用于告警和容量评估
- 对用户可展示温和提示(如“正在重试…” → “服务暂不稳定,已启用简化模式”),增强信任感
不复杂但容易忽略:try-catch 是开关,退避是节拍器,降级是安全气囊——三者缺一不可。真正优雅的 await,是你让它“等得明白、退得从容、兜得住底”。











