websocket断线重连时消息队列缓冲的核心是“判”和“控”:只缓存关键业务消息(如auth、subscribe、订单操作),用数组管理队列,重连后按序发送并配合服务端确认去重,避免重复与乱序。

WebSocket 断线重连时实现消息队列缓冲,核心是:连接断开时不丢消息、重连成功后按序补发、避免重复或乱序。关键不在“存”,而在“判”和“控”——即判断哪些该缓存、何时该发、发完如何清理。
哪些消息需要进队列?
不是所有消息都要缓存。应只缓存业务关键、不可丢失、有上下文依赖的消息,比如:
- 登录后的身份认证指令(如
{"type":"auth","token":"xxx"}) - 频道订阅请求(如
{"type":"subscribe","channel":"chat:1001"}) - 用户主动发送的业务操作(如订单提交、协作编辑指令)
- 不缓存心跳包、状态通知、纯展示类广播消息
怎么安全地缓存和管理队列?
用一个轻量级数组 + 状态控制即可,无需复杂结构:
- 声明一个
const messageQueue = useRef([])(React)或let messageQueue = [](原生JS),全局或实例级维护 - 每次调用
send()前,先检查ws?.readyState === WebSocket.OPEN;不满足则messageQueue.current.push(message) - 缓存内容建议为原始字符串(已序列化),避免闭包引用或状态漂移
- 队列长度建议设上限(如 50 条),超限时可丢弃最老消息或报错提示
重连成功后怎么发?
不能一股脑全发,要配合连接状态和业务语义:
- 在
onopen回调中,用循环清空队列:while (queue.length) ws.send(queue.shift()) - 对需服务端确认的关键消息(如 auth、subscribe),可加简单重试逻辑:发送后启动计时器,若指定时间未收到响应,则重发一次(最多1次)
- 避免在
onopen中直接发敏感操作(如支付),建议等收到服务端就绪确认(如{"type":"ready"})后再触发队列投递
怎么防止重复发送或状态错乱?
缓存本身不解决去重,必须靠协议层配合:
- 每条缓存消息带唯一标识(如
id: Date.now() + Math.random()或 UUID),服务端收到后记录已处理 ID - 客户端在重连成功后,可先向服务端请求“最近已处理消息ID列表”,比对后过滤本地队列中已确认项
- 清除队列前,确保新连接已稳定(例如收到首个
pong或ready消息),再执行queue.splice(0)彻底清空











