如何在Promise中初始化WebSocket并在外部使用?相关最佳实践是什么?
WebSocket实现方案解答
核心疑问解答
1. 是否需要把所有用到WebSocket的点击方法都放在Promise内部?
不需要全放入Promise内部,但必须保证调用send方法时WebSocket处于已连接可用状态。你当前的写法存在明显时序问题:如果用户在连接建立完成前点击按钮,websocket变量还是null,会直接抛出类型错误。
2. 在Promise中初始化变量但在外部使用是否属于不良实践?
是的,这属于典型的不良实践。WebSocket初始化是异步操作,外部代码完全无法确定访问该变量时,它处于未初始化/连接中/已连接/已断开的哪种状态,状态不可控会产生大量不可预期的运行时错误。
最佳实现方案
建议封装一个统一的WebSocket管理模块,自动处理状态管理、消息队列、重连逻辑,对外仅暴露简单的调用方法,外部业务代码不需要感知连接状态:
// WebSocket统一管理对象 const WSManager = { wsInstance: null, // 可选状态:disconnected(未连接)/connecting(连接中)/connected(已连接) status: 'disconnected', // 待发送消息队列,未连接时先缓存消息 pendingMsgQueue: [], retryTimes: 0, // 最大自动重连次数,超出后提示用户手动重连 maxRetry: 5, // 建立连接方法 connect() { if (this.status === 'connecting' || this.status === 'connected') return this.status = 'connecting' this.wsInstance = new WebSocket("ws://localhost:8080") this.wsInstance.onopen = () => { this.status = 'connected' this.retryTimes = 0 // 连接建立后批量发送队列中缓存的消息 this.pendingMsgQueue.forEach(msg => this.wsInstance.send(msg)) this.pendingMsgQueue = [] } this.wsInstance.onmessage = (e) => { // 统一处理服务端返回的消息 // 此处可扩展回调注册逻辑,分发不同消息到对应业务处理函数 } this.wsInstance.onerror = () => { this.status = 'disconnected' // 此处触发连接错误的提示 } this.wsInstance.onclose = () => { this.status = 'disconnected' // 自动重连逻辑 if (this.retryTimes < this.maxRetry) { this.retryTimes++ setTimeout(() => this.connect(), 1000 * this.retryTimes) } else { // 超出重连次数,弹出手动重连提示模态框 } } }, // 对外暴露的发送消息方法,业务侧直接调用即可 sendMsg(msg) { if (this.status === 'connected') { this.wsInstance.send(msg) } else { this.pendingMsgQueue.push(msg) if (this.status === 'disconnected') { this.connect() } } }, // 手动重连方法,给用户触发重连的按钮调用 manualReconnect() { this.retryTimes = 0 this.connect() } } // 页面初始化时启动连接 WSManager.connect() // 业务侧点击事件直接调用,不需要关心连接状态 document.getElementById("btnAnnullaStampa").addEventListener("click", () => { const loginMsg = `<LOGIN><COD>${codope}</COD><PSW>${password}</PSW></LOGIN>` WSManager.sendMsg(loginMsg) })
该方案的优势:
- 所有WebSocket逻辑内聚在管理对象内部,没有全局变量污染,避免外部意外修改状态
- 自动处理异步时序问题,未连接时的消息会自动缓存,连接成功后自动发送
- 自带自动重试、手动重连能力,符合你要求的连接异常提示用户的需求
- 业务代码不需要感知连接逻辑,调用方式简单统一
内容的提问来源于stack exchange,提问作者NiceToMytyuk
相关产品推荐
相关产品推荐

