background sync api不能在html中直接使用,必须通过service worker注册并触发;页面js仅能调用registration.sync.register()注册任务,同步逻辑必须写在sw中监听'sync'事件,且需用event.waituntil()包裹promise。

Background Sync API 在 HTML 中根本不能直接用
Background Sync 是浏览器提供的底层能力,必须通过 Service Worker 注册并触发,纯 HTML 页面(哪怕带 <script></script>)无法调用 navigator.serviceWorker.ready 之后的 registration.sync.register()。常见错误是把同步逻辑写在页面 JS 里,结果控制台报错:Uncaught TypeError: Cannot read property 'sync' of undefined——因为此时 registration 是空或未就绪。
真正能用 Background Sync 的最小闭环是:HTML 页面注册 SW → SW 安装激活 → 页面触发 sync 事件注册 → 网络恢复时 SW 自动执行 sync 事件监听函数。
- 必须先成功注册并激活 Service Worker,且 SW 文件本身要响应
sync事件 - 页面 JS 只能调用
registration.sync.register('my-tag'),不能定义同步逻辑 - Chrome 和 Edge 支持较完整,Firefox 仅支持
periodicSync(需 Manifest 配置),Safari 不支持
Service Worker 里怎么正确监听 sync 事件
SW 脚本中监听 sync 事件必须用 self.addEventListener('sync', ...),且内部必须返回一个 Promise(否则浏览器认为任务失败,可能拒绝下次触发)。常见错误是忘记 event.waitUntil() 包裹,或在其中用了不返回 Promise 的操作(如直接调用 fetch() 却没 return)。
self.addEventListener('sync', event => {
if (event.tag === 'send-logs') {
event.waitUntil(
fetch('/api/log', {
method: 'POST',
body: JSON.stringify(cachedLogs),
headers: { 'Content-Type': 'application/json' }
})
.then(res => res.json())
.then(() => caches.delete('log-cache'))
);
}
});
-
event.tag必须和页面注册时传入的字符串严格一致(区分大小写) -
event.waitUntil()内部 Promise 若 reject,浏览器会记录失败但不会重试;若 resolve,才算成功完成一次同步 - 不要在
sync事件里读取 DOM 或window对象——SW 没有这些上下文
为什么注册 sync 失败却没报错
调用 registration.sync.register('tag') 后,如果返回 Promise reject,通常是因为:SW 未激活、浏览器不支持、同一 tag 已注册未完成、或用户禁用了后台同步(如 Chrome 的 chrome://settings/content/backgroundSync)。但这个 reject 很容易被忽略,因为没人 catch。
- 务必用
.catch(err => console.error('Sync register failed:', err))捕获失败 - 某些安卓 WebView 或 PWA 安装后首次启动时 SW 尚未激活,
registration.sync是undefined,需加判断 - Chrome 90+ 对未安装为 PWA 的网页限制更严,即使有 manifest,也只允许已添加到主屏幕的页面使用 Background Sync
替代方案比硬扛 Background Sync 更实际
Background Sync 的兼容性差、调试困难、失败静默、且只在“离线→上线”瞬间触发一次,很多场景下不如主动策略可靠。
- 表单提交失败时,用
localStorage存原始数据 + 页面轮询navigator.onLine,上线后立即重发(简单可控) - 需要周期性同步(如每小时拉新消息),改用
periodicSync(需manifest.json声明"periodic_sync" : {"minPeriod": 3600}) - 对 iOS 用户,只能降级为页面可见时检查网络并同步(监听
visibilitychange+fetch)
真正难的不是写对那几行 sync.register(),而是设计一套跨浏览器、可观测、能降级的数据同步状态机——Background Sync 只是其中一环,而且是最不可靠的一环。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











