如何实现 Fetch 请求超时降级:3 秒未响应则自动切换备用 API

本文详解如何通过 promise.race 实现 fetch 请求的超时控制与备用链路降级,避免阻塞 ui,并确保在主 api 响应超 3 秒时无缝切换至备用接口。

前端开发中,依赖第三方 API 时常面临网络延迟、服务不可用等问题。单纯用 if 判断无法实现“等待超时后执行另一请求”,因为 fetch() 是异步操作,其耗时不支持同步条件判断(如 if (timeTaken > 3000))。正确方案是利用 Promise.race() —— 它会返回首个 settled(fulfilled 或 rejected)的 Promise,从而天然支持超时竞争机制。

✅ 推荐实现:使用 Promise.race + timeout Promise

// 创建一个在指定毫秒后 reject 的超时 Promise
function timeout(ms, promise) {
  return Promise.race([
    promise,
    new Promise((_, reject) =>
      setTimeout(() => reject(new Error(`Request timed out after ${ms}ms`)), ms)
    )
  ]);
}

// 主逻辑:优先请求 link1,3 秒未响应则 fallback 到 link2
const requestOptions = {
  method: 'GET',
  headers: {
    'apikey': 'your-api-key' // 请替换为实际 key
  }
};

timeout(3000, 
  fetch('https://api.apilayer.com/exchangerates_data/latest?base=USD', requestOptions)
)
.then(response => {
  if (!response.ok) throw new Error(`HTTP ${response.status}`);
  return response.json();
})
.then(data => {
  console.log('✅ Primary API success:', data);
  // 处理主数据逻辑(如渲染汇率)
})
.catch(error => {
  console.warn('⚠️ Primary API failed or timed out:', error.message);
  // 降级请求备用 API
  return fetch('https://api.apilayer.com/fixer/latest?base=USD', requestOptions)
    .then(res => {
      if (!res.ok) throw new Error(`Fallback HTTP ${res.status}`);
      return res.json();
    })
    .then(data => {
      console.log('✅ Fallback API success:', data);
      // 处理备用数据逻辑
    })
    .catch(err => {
      console.error('❌ Both APIs failed:', err);
      // 统一错误处理:提示用户、显示离线状态、启用缓存等
    });
});

⚠️ 关键注意事项

  • 不要滥用 if/else 同步判断:fetch() 返回 Promise,其执行时间无法在调用瞬间获知,if () { fetch(...) } else { fetch(...) } 实际会同时触发两个请求永远只走 if 分支,完全违背设计意图。
  • Promise.race 是核心:它让「主请求」和「超时拒绝」形成竞态,3 秒内完成则取主结果;超时则立即 reject,触发 .catch() 中的降级逻辑。
  • 错误需分层处理:主请求可能因网络、4xx/5xx、CORS 等失败,超时只是其中一种场景。建议在 .catch() 中统一判断错误类型,必要时再发起 fallback。
  • 避免重复请求:上述代码确保最多只发起 1 次主请求 + 1 次备用请求(仅当主请求失败/超时时),符合性能与资源节约原则。
  • 可扩展性建议:如需多级 fallback 或重试策略,可封装为通用函数,例如 fetchWithFallback(url1, url2, options, timeoutMs = 3000)。

通过该模式,你不仅能优雅解决超时降级问题,还能提升应用健壮性与用户体验——这才是现代前端异步容错的正确实践。