websocket实现实时通信需建立持久双向tcp连接,协议必须为ws://或wss://,发送前检查readystate为open,接收时手动json解析并防错,同时监听onerror和onclose实现带退避的可靠重连。

JavaScript 的 WebSocket 实现实时通信,核心是建立一个持久、双向的 TCP 连接,让浏览器和服务器能随时互发数据,而不是靠轮询或长连接“假实时”。它本身不保证业务层的“实时体验”,真正做到低延迟、不断连、不错乱,得靠前端正确使用 + 后端配合设计。
连接必须用 ws:// 或 wss:// 协议
不能写成 http:// 或直接省略协议。浏览器会直接报错,比如:
- Failed to construct 'WebSocket': The URL 'http://...' is invalid —— 地址协议错误
- net::ERR_CONNECTION_REFUSED —— 后端没启动,或端口不对
- 403 Forbidden —— 服务端校验 Origin、token 或路径失败,常见于鉴权未传参
推荐把 token 放在 URL 查询参数里,例如:wss://api.example.com/realtime?token=abc123
浏览器握手阶段不支持自定义 header,所以别试图在请求头里塞 Authorization。
发消息前务必检查 readyState
连接不是瞬间就绪的。new WebSocket() 后立即 send(),大概率静默失败。readyState 有四个值:
- 0(CONNECTING):正在握手,还没通
- 1(OPEN):可安全 send()
- 2(CLOSING):正在关闭
- 3(CLOSED):已断开
正确做法是:
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({ type: 'chat', text: 'hi' }));
} else if (ws.readyState === WebSocket.CONNECTING) {
// 可缓存待发消息,等 onopen 触发后再补发
}
别用 setTimeout 等固定毫秒数——网络延迟不可控,onopen 才是唯一可靠信号。
收消息要手动解析 JSON,且防错处理
WebSocket 传的是原始字符串或二进制帧,不是自动解包的对象。服务端每 send 一次,前端 onmessage 就收到一个完整帧(不会粘包),但内容仍是字符串:
ws.onmessage = (event) => {
try {
const data = JSON.parse(event.data);
console.log('收到:', data);
} catch (e) {
console.warn('非法JSON:', event.data);
}
};
如果服务端用 Node.js 的 ws 库,确保每次 socket.send() 发的是独立 JSON 字符串,不要拼接流式输出,否则前端 parse 会失败。
连接异常必须同时监听 onerror 和 onclose
断连时,onerror 和 onclose 可能先后触发,也可能只触发其一。只监听 onclose 容易漏掉底层错误(比如证书失效、DNS 失败)。建议:
- onerror 中记日志,但不直接重连(可能只是临时抖动)
- onclose 中判断 event.code 和 event.reason,区分是主动关闭还是意外中断
- 实现带退避策略的重连(如首次 1s,失败后 2s、4s、8s…上限 30s)
重连前检查是否已手动 close(),避免重复创建实例;重连次数过多时应提示用户或降级为轮询。
不复杂但容易忽略
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











