WebSocket需显式绑定onopen、onmessage、onclose、onerror四个事件,漏绑onerror会导致异常静默;onmessage需按event.data类型安全解析;send前须检查readyState===WebSocket.OPEN。

WebSocket 的事件监听不是“一次性注册所有事件”的操作,而是必须显式为每个事件分别赋值回调函数。不存在 onall 或批量监听 API,漏掉任一事件(尤其是 onerror)会导致连接异常时静默失败。
必须手动绑定的四个核心事件
浏览器原生 WebSocket 对象只暴露四个可写属性:它们不是事件名字符串,而是直接可赋值的函数引用。不设置就等于放弃响应——比如没设 onerror,连接被防火墙中断时你根本收不到任何提示。
-
onopen:仅在握手成功、readyState === 1后触发一次,适合发初始化消息 -
onmessage:每次收到服务器数据都触发,event.data类型取决于服务端发送格式(可能是string、Blob或ArrayBuffer) -
onclose:连接关闭时触发,event.code和event.reason可辅助判断是主动断开还是网络闪断 -
onerror:只要连接过程出错(DNS 失败、SSL 证书无效、跨域拒绝等)就会触发,但不会提供详细错误堆栈,仅传入一个空Event对象
onmessage 中如何安全解析 event.data
服务端可能发文本或二进制,而 event.data 类型不固定。直接调用 .toString() 在二进制场景会返回 [object Blob],导致 JSON 解析失败。
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
- 先检查
typeof event.data === 'string',再尝试JSON.parse() - 若为
instanceof Blob,需用event.data.text()(返回 Promise)或new FileReader()读取 - 若为
instanceof ArrayBuffer,可用new TextDecoder().decode(event.data)转字符串 - 避免在
onmessage里做耗时同步操作(如大数组排序),否则会阻塞后续消息处理
给 onmessage 回调传额外参数的三种写法
类实例方法作为 onmessage 处理器时,常需访问 this 或其他上下文变量。直接赋值 ws.onmessage = this.handleMessage 会丢失 this 绑定。
- 用箭头函数:
ws.onmessage = (event) => this.handleMessage(event, this.userId, this.roomId)—— 简洁,但注意闭包中变量是否会被意外覆盖 - 用
bind:ws.onmessage = this.handleMessage.bind(this, this.userId, this.roomId)—— 参数顺序固定,event会自动追加到末尾 - 用闭包包装:
const self = this; ws.onmessage = function(event) { self.handleMessage(event, self.userId); }—— 兼容性最好,但需防self引用失效(如组件已销毁)
容易忽略的 readyState 检查时机
很多人在 onopen 外直接调用 ws.send(),却没意识到:如果 ws 实例刚创建、readyState 还是 0(CONNECTING),send() 会立刻抛错并中断后续逻辑。
- 所有
send()调用前必须加if (ws.readyState === WebSocket.OPEN)判断 - 不要依赖
onopen触发后就“永远安全”,网络抖动可能导致readyState突然变回CLOSED - 重连逻辑里,新
WebSocket实例的readyState初始值就是0,不是OPEN
真正难的不是绑事件,而是让每个事件回调都能在连接生命周期的任意时刻稳定执行——尤其当页面隐藏、设备休眠、代理中断时,onclose 和 onerror 的触发时机与参数可靠性远比文档写的更模糊。

















