请求队列通过缓存请求参数、监听网络状态、限制重试次数及封装fetch函数,实现离线暂存与在线自动重试,提升应用健壮性;需配合请求id幂等防护与轻量探测确保可靠性。

在网络不稳定或断开时,直接调用 fetch 通常会失败并抛出异常,导致请求丢失。利用请求队列(Request Queue)可以将失败的请求暂存起来,在网络恢复后自动重试,从而提升应用的健壮性和用户体验。
设计一个内存型请求队列
请求队列本质是一个待执行请求的缓存结构,可基于数组 + 定时轮询 / 网络状态监听实现。关键点在于:只缓存请求参数(URL、method、body、headers 等),不缓存原始 fetch 调用本身(避免闭包捕获过期状态)。
- 用
Array存储待重试请求对象,每个对象包含完整 fetch 配置和一个重试计数器 - 为防无限重试,建议设置最大重试次数(如 3 次),超限后触发失败回调或丢弃
- 队列应支持添加(push)、取出(shift)、清空(clear)等基础操作
监听网络状态变化
使用 navigator.onLine 判断初始连接状态,并监听 online 和 offline 全局事件来响应切换:
-
offline触发时,暂停主动发起新请求(可拦截业务层调用,转为入队) -
online触发时,启动队列消费逻辑 —— 逐个尝试发送,成功则移除,失败则按策略决定是否重入队 - 注意:
navigator.onLine并非 100% 可靠(比如 WiFi 已连但无外网),建议配合一次轻量级探测(如 GET /health)确认真实可达性
封装带队列的 fetch 函数
提供统一入口,内部自动处理排队与重试逻辑:
- 调用时先检查
navigator.onLine,若离线则将请求配置推入队列并返回一个 pending Promise(可 resolve 为{ queued: true }) - 若在线,则直接
fetch;失败且是网络错误(TypeError或 status 0),则入队并返回 pending Promise - 队列消费函数使用
setTimeout或Promise.race控制并发(如每次最多 2 个并发重试),避免雪崩
处理重复提交与幂等性
重试可能引发重复请求,需在服务端或客户端做防护:
- 客户端生成唯一请求 ID(如 UUID),附在请求头(
X-Request-ID)中,便于后端去重或幂等判断 - 对非幂等操作(如 POST 创建资源),建议服务端支持
Idempotency-Key头,保证相同 key 的多次请求只生效一次 - 前端可在队列中按 URL + method + body hash 去重,避免重复入队
不复杂但容易忽略。核心是把“失败即丢弃”变成“失败即暂存+择机再试”,配合网络状态感知和合理重试策略,就能让应用在网络抖动时依然可靠运行。











