uniapp中websocket关闭失败问题解决,防止一个应用多个websocket实例并清理无彻底

前端开发websocket的过程是页面初始化后创建了websocket长连接,然后心跳检测,在意外关闭后重重连websocket,离开页面后就对websocket进行销毁,这是很正常的逻辑。

然后在开发过程发现一个问题,离开页面后定时器依然在检测心跳,而且离开后会关闭一次然后被重新连接了,这会导致后台推送数据的时候多次重复出现,甚至在多个不同聊天人之间也出现原来的用户聊天推送(在其它端口推送时,后台根据用户id推送)。


之前前端同事对接出现这个问题就没解决,后台是没问题的,前端同事也不想多干活,反正就是不愿意处理。


现在我自己开发自己的项目,自己图手写了个聊天客服,如下图一样。然后发现了这个问题是普遍存在的,而且就是前端未能清理socket的问题,导致消息混乱


一开始页面的清理是这样的

beforeDestroy() {
  console.log('页面销毁')
  this.closeWebSocket();
},
onUnload() {
  console.log('页面卸载')
  this.closeWebSocket();
},

//关闭清理的方法
closeWebSocket() {
  if (this.websocket) {
    this.websocket.close();
    this.websocket = null;
  }
  if (this.heartbeatInterval) { // 清除心跳检测定时器
    clearInterval(this.heartbeatInterval);
    this.heartbeatInterval = null;
  }
},

//websocket关闭监听函数
// 处理 WebSocket 关闭
handleWebSocketClose() {
  if (this.reconnectTimes < this.maxReconnectTimes) {
    setTimeout(() => {
      this.reconnectTimes++
      this.connectWebSocket()
    }, 3000)
  } else {
    this.isServiceOnline = false
    uni.showToast({
      title: '客服暂时离线,请留言',
      icon: 'none'
    })
  }
},


知道问题是websocket未清理彻底的问题就好办了,解决起来也简单,就是在卸载页面的时候价加上状态,比如leave=true,然后这个状态成立的时候不允许重连即可。根源的问题是重连发生的。修改如下

beforeDestroy() {
  console.log('页面销毁')
  this.leave = true
  this.closeWebSocket();
},
onUnload() {
  console.log('页面卸载')
  this.leave = true
  this.closeWebSocket();
},


// 处理 WebSocket 关闭
handleWebSocketClose() {
  if (this.leave){
    console.log('页面已离开,不再重连');
    return ;
  }
  if (this.reconnectTimes < this.maxReconnectTimes) {
    setTimeout(() => {
      this.reconnectTimes++
      this.connectWebSocket()
    }, 3000)
  } else {
    this.isServiceOnline = false
    uni.showToast({
      title: '客服暂时离线,请留言',
      icon: 'none'
    })
  }
},

就是在卸载和销毁页面的时候做状态,防止被重连了。


image.png

评论/留言