Service Worker 不能直接发起后台同步请求,需通过 Background Sync API 在网络恢复时自动重试未完成请求;该 API 需 HTTPS、在激活的 SW 中监听 sync 事件,配合 IndexedDB 存储数据并调用 registration.sync.register() 注册任务。

Service Worker 本身不能直接发起“后台同步请求”,它没有网络请求的主动触发能力,但可以通过 Background Sync API 实现“在条件满足时(如网络恢复)自动重试未完成的请求”,这才是常说的“后台同步”的核心机制。
Background Sync 是什么?
Background Sync 是一个浏览器 API,允许 Service Worker 在网络可用时,自动执行之前注册的同步任务。它不是实时同步,而是“延迟重试”——比如用户离线时提交了表单,等设备联网后,Service Worker 会自动补发请求。
- 需要 HTTPS(本地开发可使用 localhost)
- 必须在已激活的 Service Worker 中注册同步事件监听
- 同步任务由浏览器控制时机,不保证立即执行,也不保证只执行一次
如何注册后台同步任务
在页面脚本中(非 Service Worker),调用 registration.sync.register() 请求一次同步:
// 页面中:提交表单后尝试注册同步
if ('serviceWorker' in navigator && 'sync' in registration) {
navigator.serviceWorker.ready.then(reg => {
reg.sync.register('submit-order'); // 注册名为 'submit-order' 的同步任务
});
}注意:不能在页面加载时盲目注册,应结合业务逻辑(如 API 调用失败且处于离线状态时再注册)。
立即学习“Java免费学习笔记(深入)”;
在 Service Worker 中响应 sync 事件
在 Service Worker 文件中监听 sync 事件,并执行实际网络请求:
// sw.js
self.addEventListener('sync', event => {
if (event.tag === 'submit-order') {
event.waitUntil(
fetch('/api/order', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ /* 之前存好的数据 */ })
})
.then(res => {
if (!res.ok) throw new Error('Sync failed');
// 成功后可清理缓存或发送通知
})
.catch(err => {
console.error('Sync retry failed:', err);
// 可选择再次注册 sync(谨慎!避免无限循环)
})
);
}
});关键点:
-
event.waitUntil()必须包裹异步操作,否则浏览器可能中断任务 - 请求体数据需提前存储(如用 IndexedDB 或 Cache API),Service Worker 无法访问页面变量
- 失败后不要自动重注册 sync,建议加退避策略或人工干预
配套:离线时保存待同步数据
单纯注册 sync 不够,你还得把要发的数据先存下来:
- 用
indexedDB存结构化数据(推荐),例如订单内容、时间戳、唯一 ID - 在 sync 回调里读取对应数据并发送,成功后从 DB 删除
- 避免在 sync 中执行耗时操作(如大量计算),保持轻量
示例思路:页面提交失败 → 存入 indexedDB → 调用 sync.register() → SW 触发 sync → 读 DB → 发请求 → 清理 DB。
不复杂但容易忽略:Background Sync 不是轮询,也不是实时推送,它是浏览器提供的“可靠重试通道”。用对场景(如表单提交、消息发送、状态上报),再配好数据持久化和错误处理,就能真正实现离线优先的健壮同步。


















