HTML5中断网重连时,Service Worker协同页面脚本实现表单离线暂存与自动重发闭环:用IndexedDB结构化存储表单(含唯一ID、序列化数据、时间戳、重试次数等),SW通过Background Sync或online事件触发重发,重发前校验真实连通性并指数退避,成功后清理数据并postMessage通知页面反馈。

HTML5 中断网重连时,Service Worker 本身不直接“恢复表单”,而是配合前端逻辑,实现离线暂存 → 网络恢复自动重发 → 成功后清理与反馈的闭环。关键不在 SW 单独干活,而在它和页面脚本协同接管网络生命周期。
用 IndexedDB 队列暂存未提交的表单数据
localStorage 容量小、同步阻塞、不支持事务,不适合表单重发场景。应改用 IndexedDB 存储结构化表单数据:
- 每条记录包含:表单唯一标识(如 UUID 或 URL+时间戳)、序列化字段(JSON.stringify(formData))、提交时间、重试次数、目标 API 地址
- 在页面 submit 事件中调用
event.preventDefault(),探测失败后写入 DB,不依赖 navigator.onLine - 写入前用
indexedDB.open()确保库就绪,失败时降级到 sessionStorage(仅限简单文本字段)
Service Worker 拦截并接管重发逻辑
SW 不能主动发起 fetch(需用户交互触发),但可在网络恢复后监听 online 事件,并启动后台同步(Background Sync)或定时轮询重发:
设置基于 systemd 的看门狗,使 Node.js 长运行服务(如 Telegram 机器人、Express 仪表盘等)在 shell 退出、SSH 断开等情况下保持运行。
- 注册时启用 Background Sync:
navigator.serviceWorker.ready.then(r => r.sync.register('form-retry')) - 在 SW 的
sync事件中读取 IndexedDB(通过self.clients.matchAll()获取页面上下文后通信,或使用postMessage触发页面重发) - 若不支持 Background Sync(如 Safari),改用
online事件 + 页面主动通知 SW:“我上线了,请检查队列”
重发时必须做真实连通性验证
仅靠 online 事件不够——WiFi 已连但网关不通、DNS 失效、后端宕机等情况仍会返回 true:
立即学习“前端免费学习笔记(深入)”;
- 重发前先发一个轻量
fetch('/api/health', { method: 'HEAD', signal: AbortController.timeout(4000) }) - 健康端点需校验数据库连接、核心服务状态,不能只返回 200 OK
- 失败则延迟重试(建议指数退避:1s → 1.6s → 2.6s → 4.2s…上限 30s),并限制总重试次数(如 ≤5 次)
成功提交后清理与用户反馈
重发不是“发完就算”,必须闭环处理结果:
- fetch 成功且响应状态为 2xx 后,从 IndexedDB 删除对应记录;失败则更新重试次数并保留
- 通过
self.clients.matchAll()找到打开的页面,用client.postMessage()通知提交结果(如 { type: 'form-submitted', id: 'xxx' }) - 页面监听 message 事件,在表单旁显示 toast 提示:“已补发成功”或“仍无法提交,请检查网络”
- 敏感字段(如密码、身份证号)应在存入 IndexedDB 前加密(用 SubtleCrypto AES-GCM),密钥由页面内存持有,不持久化


















