websocket需对明确完成条件的操作promise封装:连接建立、单次消息等待、带id请求-响应;须加超时保护、状态检查及事件监听清理,避免内存泄漏与消息错配。

WebSocket 本身是事件驱动的,不能直接 await,但可以用 Promise 封装关键环节:连接建立、单次消息等待、带 ID 的请求-响应。重点不是“把整个 WebSocket 变成 Promise”,而是对**有明确完成条件的操作**做 Promise 包装,让异步流程更可控。
封装连接建立:await wsConnected()
new WebSocket() 立即返回实例,但连接是否成功需等 open 或 error 事件。用 Promise 包装可避免反复轮询 readyState:
- 创建函数 connect(url),内部 new WebSocket(url)
- 监听 open → resolve(ws);监听 error 或 timeout → reject(error)
- 设置超时(如 5s),防止无限等待;连接成功后记得移除 error 监听器,避免内存泄漏
调用示例:const ws = await connect("wss://api.example.com");
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
封装单次消息接收:await waitForMessage()
不推荐全局监听 onmessage 后手动过滤,而应为一次具体等待行为创建独立 Promise:
- 函数 waitForMessage(ws, predicate) 接收 WebSocket 实例和匹配函数(如 msg.type === "LOGIN_OK")
- 内部设标志位 isResolved,onmessage 中满足 predicate 时 resolve(data) 并设标志,再移除该监听
- 务必加超时保护,例如 Promise.race([wait, new Promise((_, r) => setTimeout(() => r(new Error("timeout")), 3000))])
封装请求-响应模式:await rpc.call("getUser", [1001])
这是最贴近实际业务的封装,适合需要“发指令、等结果”的场景(如登录、拉取数据):
- 维护一个 Map
,key 是每次请求生成的唯一 ID(可用 crypto.randomUUID()) - call(method, params) 方法中构造带 id + method + params 的 JSON,发送前存入 Map
- 全局 onmessage 解析响应,若 data.id 存在于 Map 中,则 resolve 或 reject 对应 Promise,并从 Map 删除
- 连接关闭或重连时,遍历 Map reject 所有 pending 请求,防止悬空
注意事项与避坑点
这些封装能提升可读性,但也容易引入新问题:
- 不要在未检查 readyState 的情况下调用 send(),可在 send 封装里加判断:if (ws.readyState !== WebSocket.OPEN) throw new Error("not connected")
- 避免多个 waitForMessage 同时挂起且 predicate 逻辑重叠,否则可能 resolve 错消息;应靠 request ID 或上下文字段隔离
- onmessage 是全局监听器,所有封装都要共享它,所以必须统一管理分发逻辑,不能各自重复绑定
- 服务端返回顺序 ≠ 发送顺序,业务层需依赖 ID 匹配,而非接收先后
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










