必须封装成可复用websocket类,否则将导致跨组件通信失效、重复连接、消息覆盖、心跳缺失及重连失控;核心接口仅需connect/send/on/close四个方法,内部统一处理重连、心跳、状态同步与错误恢复。

直接封装成一个可复用的 WebSocket 类,而不是每次在组件里 new 一个原生实例——这是避免状态混乱、重复连接、消息丢失和重连失控的最底线要求。
为什么不能直接在 Vue/React 组件里 new WebSocket
原生 WebSocket 实例不具备跨组件通信能力,且生命周期绑定组件后极易被销毁导致连接中断;更关键的是,onopen/onmessage 等回调是覆盖式赋值,多个组件同时监听会互相覆盖。
- 组件卸载时忘记
socket.close()→ 连接残留、内存泄漏 - 多个组件都调用
new WebSocket(url)→ 同一 URL 建立多条并发连接,后端压力陡增 -
onmessage被反复重写 → 只有最后一个组件能收到消息 - 无心跳逻辑 → 网络中间设备(如 Nginx、防火墙)静默断连,前端毫无感知
必须暴露的最小可用接口:connect / send / on / close
一个真正能进生产环境的 SDK,对外只应暴露这四个核心方法,其余细节(重连、心跳、状态同步)全部封装在内部。用户不需要知道“什么时候该发 ping”,只需要调用 send() 发消息、on('type', handler) 接收特定类型消息即可。
前端设计与 UI/UX 全方位优化专家。覆盖视觉层次、排版系统、色彩理论、响应式布局、交互体验、动画动效、无障碍访问、性能优化八大维度,帮助开发者将普通页面升级为高品质产品级界面。前端设计与 UI/UX 全方位优化专家。覆盖视觉层次、排版系统、色彩理论、响应式布局、交互体验、动画动效、无障碍访问、性能优化八大维度,帮助开发者将普通页面升级为高品质产品级界面。
-
connect():返回 Promise,成功后 resolve socket 实例,失败 reject 错误;内部自动处理重连与心跳启动 -
send(data):接受任意可序列化对象,自动JSON.stringify(),并检查readyState === 1 -
on(type, handler):按消息类型注册处理器,例如ws.on('chat', (msg) => {...}),支持多次调用不覆盖 -
close():清除所有定时器、移除事件监听、调用socket.close(),并重置内部状态
心跳与重连参数必须可配,但默认值要合理
不同网络环境对保活容忍度差异极大:内网可设 30s 心跳,公网建议 15s;重连延迟从 1s 逐步退避到 30s 更稳妥,硬编码 5s 重试在弱网下极易打爆后端连接数。
-
heartbeatInterval: 15000(15 秒):比多数云厂商 LB 超时(如阿里云 SLB 默认 60s)更保守 -
reconnectDelay: 1000(首重连延时 1s),配合maxReconnectAttempts: 10和指数退避 -
reconnectExponential: true(默认开启):第 n 次重连等待时间为Math.min(30000, delay * 2^(n-1)) - 禁止把
url写死在类里,必须由调用方传入;token、userId 等动态参数应通过headers或连接前拼接 query 实现
容易被忽略的边界问题:readyState 判断、message 解析、错误吞没
很多封装库在 send() 里只简单判断 socket.readyState === WebSocket.OPEN,但实际中 CONNECTING(0)状态也可能持续数秒,此时发消息会静默失败。
- 发送前应等待
readyState === 1,若为 0 则缓存消息,等onopen触发后批量 flush -
onmessage回调中必须 try/catchJSON.parse(),否则一条非法 JSON 就会让整个消息流中断 -
onerror不应只 console.error,必须触发重连或抛出可监听的 error 事件,否则异常完全不可追踪 - 不要在
onclose里自动重连——需先判断event.code:1000 是主动关闭,1006 是异常断开,仅后者才该重连
真正难的不是写一个能连上的封装,而是让这个连接在页面刷新、切 Tab、锁屏、弱网抖动、服务端滚动发布等各种现实场景下,依然保持「看起来一直在线」。所有自动逻辑都要留手动干预入口,比如 ws.disableHeartbeat() 或 ws.forceReconnect(),否则调试时会陷入无法控制的黑盒。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










