WebSocket通信必须异步处理:连接需监听open事件后发送消息,收发需适配事件循环与错误恢复,推荐封装sendWithAck()并用AbortController控制超时,同时手动维护发送队列、绑定错误监听并妥善捕获异常。

WebSocket 实时通信天然依赖异步编程,JavaScript 中的 Promise、async/await 和事件驱动机制是支撑可靠双向通信的关键。
WebSocket 连接本身是异步建立的
new WebSocket(url) 立即返回实例,但底层 TCP 握手和协议升级需时间。不能假设调用后就绪,必须监听 open 事件再发消息。
- 连接成功后才可调用 ws.send(),否则抛出 InvalidStateError
- 推荐在 ws.onopen 回调中初始化业务逻辑,比如发送登录凭证或订阅频道
- 避免在 new WebSocket 后立刻 send —— 此时 readyState 很可能还是 0(CONNECTING)
消息收发需适配事件循环与错误恢复
onmessage 是事件回调,天然异步执行;而网络中断、服务端重启等异常会触发 onerror 或 onclose,需主动重连。
- 用 setTimeout + 递归调用 实现指数退避重连,避免频繁建连压垮服务端
- 发送关键消息时,建议搭配服务端 ACK 机制:发消息 → 等待带 msgId 的确认响应 → 超时则重发
- 将 onmessage 处理逻辑包裹在 try/catch 内,防止解析 JSON 失败阻塞后续消息
结合 async/await 封装更可控的通信流程
原生 WebSocket API 不返回 Promise,但可轻松封装成支持 await 的工具函数,提升代码可读性与错误处理能力。
立即学习“Java免费学习笔记(深入)”;
- 封装 sendWithAck():返回 Promise,在收到服务端确认后 resolve,超时 reject
- 用 AbortController 控制超时,避免“永远等待”问题
- 示例:const result = await ws.sendWithAck({ type: 'fetch-data', id: 123 });
避免常见异步陷阱
多个并发 send 调用不会自动排队;未监听 close/error 可能导致静默失败;Promise 链中未 catch 会丢失错误。
- 手动维护发送队列(如用 Array + setInterval 检查 readyState),确保顺序发送
- 始终绑定 ws.onerror 和 ws.onclose,记录日志并触发降级策略(如切 HTTP 轮询)
- 在 async 函数中使用 WebSocket 时,确保所有 await 调用都包裹在 try/catch 中











