用 IndexedDB 实现离线消息队列的核心是:先将待发消息以自增主键、status 索引存入 messages 仓库,离线时原子写入 pending 消息,网络恢复后通过 online 事件+健康探测触发同步,按 timestamp 升序批量发送并更新 status,配合 UUID 幂等标识与服务端协同去重。

用 IndexedDB 实现离线消息队列,核心是把待发送的消息先存进数据库,等网络恢复再批量读取、发送并删除。关键在于可靠写入、状态标记、重试机制和网络监听。
创建消息存储对象仓库
初始化数据库时定义一个 messages 仓库,用自增主键(autoIncrement)确保每条消息有序且唯一,并添加索引便于按状态查询:
- 主键字段设为
id(number,自增) - 必存字段包括:
data(原始消息内容,建议 JSON 字符串)、timestamp(毫秒时间戳)、status("pending"或"sent") - 对
status建索引,方便快速查出所有未发送消息
离线时安全写入待发消息
发送前先检测网络:navigator.onLine === false 或 fetch() 失败后触发降级流程。写入时用事务确保原子性:
- 调用
db.transaction(['messages'], 'readwrite') - 获取
objectStore,用add({ data: JSON.stringify(msg), status: 'pending', timestamp: Date.now() }) - 监听
onsuccess确认写入完成,再通知 UI “已缓存”;onerror中记录错误并提示用户
监听网络恢复并自动同步
利用 window.addEventListener('online', ...) 触发同步逻辑,但注意该事件不保证网络真正可用,需配合试探请求:
- 收到
online事件后,先发起一个轻量HEAD或GET /health请求验证连通性 - 验证通过,开启事务读取所有
status === 'pending'的消息(按timestamp升序) - 逐条或批量(如 5 条/批)调用
fetch发送;成功后更新对应记录的status = 'sent'并删除(或保留日志) - 任一失败则暂停当前批次,记录错误,稍后重试(可用
setTimeout延迟 5 秒再试)
处理发送失败与幂等性
服务端必须支持幂等设计(如消息带唯一 messageId),避免重复提交。前端也要做基础防护:
- 每条消息生成 UUID 或组合时间戳+随机数作为
id字段,随数据一起存入 IndexedDB - 发送时将该
id放在请求头或 body 中,服务端据此去重 - 若响应是 5xx 或超时,仅标记为
'failed',不删除;下次同步时可重试或人工干预 - 长期失败(如超过 3 次)可触发告警或提供“手动重发”按钮
不复杂但容易忽略细节:写入要等事务完成再返回;网络判断不能只靠 onLine;每条消息必须有唯一标识;服务端必须配合幂等。做好这四点,离线队列就稳了。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











