new WebSocket() 建立连接需严格匹配协议、端口与路径,配置 Nginx 支持升级,onopen 后需探测可用性,message 中须判断 event.data 类型并安全解析,error 和 close 均需退避重连,且全程校验状态与数据可靠性。

直接用 new WebSocket() 就能建立全双工通道,但“能连上”不等于“能稳定双向通信”——关键在事件协同、数据类型判断和连接状态兜底。
WebSocket URL 必须匹配后端协议与路径
浏览器里写 new WebSocket('ws://localhost:8080') 不是随便填的地址:
-
ws://或wss://是强制前缀,http://会立刻抛SecurityError - 端口必须和服务端监听端口一致;Node.js 的
ws库跑在3000,前端就不能写8080 - 如果服务端挂载路径是
/ws/chat,前端 URL 得写成wss://yourdomain.com/ws/chat,否则握手返回404或被拒绝 - 生产环境走 Nginx 时,必须配置:
proxy_http_version 1.1、proxy_set_header Upgrade $http_upgrade、proxy_set_header Connection "upgrade",否则卡在Pending状态
onopen ≠ 连接可用,业务逻辑需主动探测
socket.onopen 只表示 TCP 握手完成、协议切换成功,不代表服务端已加载用户上下文或分配房间:
- 有些框架(如
ws)在connection回调里做鉴权,这期间发消息可能被丢弃 - 不要在
onopen里一口气send()多条初始化消息——弱网下bufferedAmount积压会触发自动断连 - 建议发一个轻量探测包:
socket.send(JSON.stringify({ type: 'ping' })),等收到服务端{ type: 'pong' }再启用主逻辑
message 事件里 event.data 类型必须手动判断
event.data 不是固定字符串,取决于后端发送方式:
立即学习“前端免费学习笔记(深入)”;
- 后端用
ws.send('hello')→ 前端event.data是string - 后端用
ws.send(Buffer.from([1,2,3]))→ 前端event.data是ArrayBuffer,需new TextDecoder().decode(event.data) - 后端发 JSON 字符串,但前端没
JSON.parse()就取.user.id,会报Cannot read property 'xxx' of string - 统一做法:先
if (typeof event.data !== 'string') return,再try { JSON.parse(event.data) },失败就console.warn()丢弃
error 和 close 都要触发重连,且必须加退避
onclose 不会在首次连接失败时触发,只管“已建立后断开”;onerror 才捕获 DNS 失败、证书错误、服务未启动等初始失败:
- 两个事件都得写重连逻辑,不能只靠
onclose -
onerror的Event对象是空的,无法定位原因;真正线索在onclose的event.code(比如1006表示异常断开,4001可能是鉴权失败) - 重连必须退避:第一次失败等
1000ms,第二次2000ms,第三次4000ms,避免雪崩式请求打垮后端 - 重连前检查
socket.readyState === WebSocket.CONNECTING || socket.readyState === WebSocket.OPEN,防止重复建连
最常被忽略的是:全双工不等于“自动可靠”,send() 返回不表示送达,onmessage 触发不表示业务逻辑就绪——所有数据流转环节都要加类型判断、错误捕获和状态校验,而不是依赖 API 表面行为。



















