You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 22:45:05