WebSocket发送失败需手动实现重试缓存:检查readyState,0时暂存、1时发送、2/3时入队;监听onopen重发,添加时间戳、重试次数、唯一ID;离线时可localStorage持久化。

WebSocket 发送消息失败时无法自动重试或缓存,因为 socket.send() 在连接断开或未就绪时会直接抛出异常(如 InvalidStateError),而 WebSocket 本身不提供内置队列机制。你需要手动实现“发送前检查 + 失败缓存 + 连接恢复后重发”的逻辑。
判断连接状态再发送,避免直接报错
不要无条件调用 send(),先检查 socket.readyState:
-
0(CONNECTING):正在连接,暂存消息,等待
open事件 - 1(OPEN):可安全发送
- 2(CLOSING)或 3(CLOSED):不可发送,加入缓存队列
示例:
function safeSend(socket, data) {
if (socket.readyState === WebSocket.OPEN) {
socket.send(JSON.stringify(data));
} else {
queue.push(data); // 加入待发队列
}
}
用数组维护消息队列,并监听连接恢复
声明一个全局/闭包内的数组(如 const queue = []),并在关键生命周期事件中管理它:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
- 监听
socket.onopen:遍历并清空队列,逐条发送(注意节流,避免突发大量 send 导致阻塞) - 监听
socket.onclose或socket.onerror:不主动清空队列,保留待重发项 - 可选:设置最大缓存条数(如 100 条),超限时丢弃最旧消息,防止内存泄漏
增强可靠性:添加简单重试与过期机制
纯队列不够健壮,建议为每条缓存消息附加元数据:
- 时间戳:用于判断是否超时(如 5 分钟未发出则丢弃)
- 重试次数:每次重发失败后 +1,超过阈值(如 3 次)则触发错误回调或本地持久化
- 唯一 ID:便于服务端去重或前端调试追踪
例如:
queue.push({
id: Date.now() + '-' + Math.random().toString(36).substr(2, 9),
data: { type: 'chat', msg: 'hi' },
timestamp: Date.now(),
retries: 0
});
补充:离线时可降级到 localStorage 持久化
如果页面可能长期离线(如 PWA 场景),可在队列满或页面卸载前将消息写入 localStorage:
- 监听
beforeunload或pagehide事件,序列化队列保存 - 页面重新加载后,读取 localStorage 并合并进内存队列
- 注意清理:成功发送并收到服务端确认(如 ACK 响应)后,才从 localStorage 中移除对应项

















