离线表单数据应存为含唯一id、timestamp、status、retryCount的结构化对象,通过navigator.onLine结合轻量探测请求检测真实联网状态,同步时串行提交并原子更新本地状态,服务端需幂等校验。

断网时表单数据怎么存才方便后续同步
离线数据必须持久化到本地,且结构要能支持重试、去重、状态标记。直接用 localStorage 存原始表单对象是危险的——没 ID、没时间戳、没同步状态,恢复后根本分不清哪些是新提交、哪些已发过但失败了。
推荐结构:
{ "id": "sync_20240521_abc123", "formName": "userApply", "data": { "name": "张三", "phone": "138..." }, "timestamp": 1716302455678, "status": "pending", "retryCount": 0 }其中 id 必须全局唯一(可用 Date.now() + 随机字符串),status 字段用于区分 pending / syncing / success / failed。
实际写入前建议用 JSON.stringify() 转义,并捕获异常(比如用户禁用 localStorage):
try { localStorage.setItem('offline_queue', JSON.stringify(queue)); } catch (e) { console.error('本地存储失败:', e); }
怎么可靠检测网络是否恢复
别只监听 navigator.onLine,它在 Chrome/Firefox 中对「假在线」(如仅连上 WiFi 但无外网)完全不敏感。真实场景中更常见的是请求 404 或超时,而非 online 事件触发。
正确做法是组合使用:
- 监听
window.addEventListener('online', ...)做初步响应 - 立即发起一个轻量探测请求(如
HEAD /health或GET /api/v1/ping)验证真实连通性 - 失败则退回到定时轮询(如每 5 秒一次),直到探测成功
layui.use('jquery') 不影响这个逻辑,但所有 AJAX 必须统一走 $.ajax 或封装后的请求函数,才能拦截失败并进队列。
同步队列时如何避免重复提交和状态错乱
核心原则:每个请求必须原子化更新本地状态,且服务端需幂等。前端不能只靠「发完就删」,而要「收到 200 再删 + 更新 status」。
批量同步建议串行执行(非并行),否则并发请求可能因服务端限流或数据库锁导致部分成功部分失败,状态难以对齐:
- 从
localStorage读出所有status === 'pending'的条目 - 按
timestamp升序逐个发送(保证业务顺序) - 每次请求的
complete回调里,用localStorage.setItem更新该条目的status和retryCount - 若响应非 200,
retryCount+1,超过 3 次标为failed并暂停队列
id 去重,例如用 Redis 的 SETNX 或数据库唯一索引。
Layui 表单提交拦截与离线适配怎么写
不要改 Layui 的 form.on('submit(...)') 默认行为后手动发 AJAX——那样会丢失 Layui 的校验、加载态、提示等能力。应该在提交回调里做判断:
form.on('submit(saveBtn)', function(data){<br> if (!navigator.onLine) {<br> saveToOfflineQueue(data.field); // 存入本地队列<br> layer.msg('已离线保存,网络恢复后自动同步');<br> return false;<br> }<br> // 否则走正常 $.ajax 提交<br> $.ajax({...});<br>});
关键点:
-
saveToOfflineQueue函数必须生成唯一id,并写入完整data.field(不是 DOM 值) - 别在离线时调用
form.render()或layer.closeAll()等依赖网络的副作用 - 同步成功后,建议主动清空对应表单字段(用
form.val('formFilter', {})),避免用户误点重复提交
真正难的不是存和发,而是网络抖动时的状态收敛——比如发出去的请求服务端处理了但响应丢包,前端重试就会重复。这必须前后端约定好幂等键和补偿机制,光靠前端 localStorage 记录是不够的。


















