WebSocket断开时未送达消息需重连后补发:先缓存至本地队列,监听状态区分异常断开,重连后按序重试并依赖服务端幂等去重,高优消息可持久化localStorage。

WebSocket 连接断开时,未送达的消息不能丢失,需在重连成功后自动补发。核心在于:本地缓存待发消息 + 监听连接状态 + 重连后按序重试。
消息发送前先入本地待发队列
所有调用 ws.send() 的消息,不直接发送,而是先存入内存队列(如 pendingQueue = []),再尝试发送。发送成功后从队列移除;若发送失败(如 ws.readyState !== 1),保留该消息并标记状态。
- 每条待发消息建议带唯一 ID 和时间戳,便于去重和排序
- 可封装发送函数,例如
sendMessage({type: 'chat', to: 'user123', content: 'hi'}) - 避免直接调用原生
ws.send(),统一走封装逻辑
监听 WebSocket 状态变化,区分主动关闭与异常断开
通过 onclose 和 onerror 捕获断连事件,但需判断是否为预期关闭(如用户退出)——只有非预期断开才触发补发准备。可用 ws.closeCode 或自定义标志位辅助判断。
- 设置
ws.isManuallyClosed = false,调用ws.close()前设为true - 在
onclose中检查该标志,为false才启动重连 + 补发流程 - 避免在页面卸载(
beforeunload)时误触发重连
重连成功后按序补发,并处理服务端重复接收
重连成功(onopen 触发)后,遍历 pendingQueue 逐条重发。服务端需配合实现“消息幂等”:根据客户端传来的消息 ID 判重,已处理则直接返回成功响应,不重复投递。
立即学习“前端免费学习笔记(深入)”;
- 前端补发时可加简单重试限制(如最多 3 次),失败消息可降级存 localStorage 待后续恢复
- 建议服务端返回 ACK 响应(如
{msg_id: 'xxx', status: 'ok'}),前端收到后清理对应队列项 - 若服务端支持,可一次性拉取离线期间的对方未读消息(即“离线消息同步”),与本地补发并行处理
补充:页面刷新或冷启动时恢复待发状态
单纯内存队列会在刷新后清空。如需更强可靠性,可将待发消息临时存入 localStorage(注意大小限制,单条不宜超 1MB),页面加载时读取并重建队列。
- 仅对高优先级消息(如重要通知、转账指令)启用持久化,普通聊天消息可舍弃
- 写入前做序列化校验,防止 JSON 解析失败导致启动异常
- 成功送达并收到服务端 ACK 后,及时清除对应 localStorage 条目
关键不在 WebSocket 多强大,而在于把“发送”拆成“排队→尝试→确认→清理”四步,并让每步可观察、可回退。服务端配合幂等设计,整套逻辑就稳了。



















