WebSocket需封装connect()等待open事件,send()不可await,应通过唯一ID匹配响应消息并用waitForMessage()等待,配合pendingRequests Map实现RPC模式。

WebSocket 本身是事件驱动的,不能直接 await ws.send() 或 await ws.receive(),因为浏览器原生 API 没有返回 Promise。但你可以用 Promise 封装关键环节,让“发完等响应”这类逻辑更清晰、可控。
连接建立必须 await
new WebSocket() 立即返回实例,但连接是否就绪需等 open 事件。直接调用 send() 可能失败。
- 封装一个
connect(url)函数,内部创建 WebSocket,监听open→ resolve;监听error或超时(如 5s)→ reject - 连接成功后,记得移除临时绑定的
error监听器,避免内存泄漏 - 调用:
const ws = await connect("wss://api.example.com");
发消息不等于收到响应,别误用 await send()
await ws.send(...) 是无效写法——send() 返回 undefined,且它只表示数据已入缓冲区,不表示服务端已处理或回传。
- 真正要等的是服务端返回的特定响应消息,比如
{ id: "req-123", result: ... } - 不要写
await ws.send(msg); const resp = await ws.recv();(recv()不是原生方法) - 正确做法:发完后主动等待匹配 ID 的那条
message,用waitForMessage(ws, predicate)封装
等一条特定消息:用 Promise 包装 onmessage
每次等待都应独立、可取消,避免多个 waitForMessage 互相干扰。
- 函数接收
ws和一个判断逻辑predicate(例如msg.id === myId) - 内部设
isResolved = false,在onmessage中满足条件时resolve(data)并设标志 - 务必加超时保护:
Promise.race([waitPromise, timeoutPromise]) - 消息匹配后,立即移除该次监听,防止后续消息误触发
实现请求-响应模式(RPC 风格)
适合登录、拉数据等“发指令、等结果”的场景,核心是靠唯一 ID 关联请求与响应。
- 维护一个
pendingRequests = new Map(),key 是随机 ID(如crypto.randomUUID()) -
call(method, params)发送前存入pendingRequests.set(id, { resolve, reject }) - 全局
onmessage解析响应,若data.id存在,则调用对应resolve()并从 Map 删除 - 连接关闭时,遍历 Map 对所有 pending 请求
reject(new Error("disconnected")),防止悬空
不复杂但容易忽略:每次 send 前检查 ws.readyState === WebSocket.OPEN,否则抛错;多个并发请求必须靠 ID 隔离,不能共用同一套等待逻辑。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











