vue封装websocket以及心跳检测、重连

发布于:2024-04-23 ⋅ 阅读:(75) ⋅ 点赞:(0)

关于websocket的封装有很多,此处记录一下自身项目已封装好的且已应用的,备份。

webSocketUtil.js:

class WebSocketUtils {
  constructor() {
    this.url = null //ws地址 或者 wss
    this.data = null
    this.isOpenSocket = false //避免重复连接
    this.timeout = 20 //隔多久执行检测 单位秒(s)
    this.heartbeatInterval = null //检测服务器端是否还存活
    this.reconnectTimeOut = null //重连之后隔多久才再次重连
  }
  // 创建websocket连接
  connectSocketInit(url) {
    if (!this.socketTask || this.socketTask.readyState === WebSocket.CLOSED) {
      this.url = url
      this.socketTask = new WebSocket(url)
      this.socketTask.onopen = (event) => {
        console.log("==============WebSocket打开连接=============", event)
        clearTimeout(this.reconnectTimeOut)
        clearInterval(this.heartbeatInterval)
        this.isOpenSocket = true
        this.socketTask.send(`ping`)
        this.startPingPong()
      }
      // 连接正常 接收消息中
      this.socketTask.onmessage = (event) => {
        console.log(event, '===========onmessage==============')
        try {
          if (event.data && event.data != 'null') {
            const jsonData = JSON.parse(event.data)
            console.log(jsonData, '===========onmessage=====jsonData=========')
          }
        } catch (err) {
          console.error('onmessage-err', err)
        }
      }

      //  socket关闭了会执行 此处
      this.socketTask.onclose = (event) => {
        console.log("========onclose============", event)
        this.isOpenSocket = false
        this.socketTask = null
        this.stopPingPong()
        if (event.code !== 4000) {
          setTimeout(() => {
            console.log('=========关闭重连reconnect===========')
            this.reconnect()
          }, 3000)
        }
      }
      this.socketTask.onerror = (error) => {
        console.log('============onerror============', error)
      }
    } else {
      console.log('Soeket exists, no need to create it, 链接状态:', this.socketTask.readyState === WebSocket.OPEN)
    }
  }

  //发送消息
  send(message) {
    //  连接正常打开时 ,才能正常成功发送消息
    if (this.socketTask && this.socketTask.readyState === WebSocket.OPEN) {
      this.socketTask.send(message)
    }
  }
  //重新连接
  reconnect() {
    const _this = this

    if (!_this.url) {
      return
    }
    //停止发送心跳
    clearInterval(_this.heartbeatInterval)
    //如果不是人为关闭的话,进行重连
    if (!_this.isOpenSocket) {
      _this.reconnectTimeOut = setTimeout(() => {
        _this.connectSocketInit(_this.url)
      }, 3000)
    }
  }
  // 关闭 WebSocket 连接
  closeSocket(code = 4000, reason = '关闭') {
    const _this = this
    _this.socketTask.close(code,reason)
    _this.data = null
    _this.url = null
    _this.isOpenSocket = false
    // _this.socketTask = null
    clearTimeout(_this.reconnectTimeOut)
    clearInterval(_this.heartbeatInterval)
    console.log('===============关闭 WebSocket 成功===================')
  }
  //开启心跳检测
  startPingPong() {
    const _this = this

    if (_this.heartbeatInterval) {
      clearInterval(_this.heartbeatInterval);
    }

    _this.data = { value: "ping", name: "心跳检测" }
    _this.heartbeatInterval = setInterval(() => {
      // console.log('==========开启心跳检测====', _this.data)
      _this.send(JSON.stringify(_this.data))
    }, _this.timeout * 1000)
  }
  stopPingPong() {
    // 停止Ping-Pong定时器
    if (this.heartbeatInterval) {
      clearInterval(this.heartbeatInterval);
      this.heartbeatInterval = null;
    }
  }

  //将获的取消息导出外部
  exportMessage(callback) {
    this.socketTask.onmessage = (res) => {
      console.log(res, '===============exportMessage============')
      try {
        return callback(res.data)
      } catch (err) {
        console.error('exportMessage-err', err)
        return callback(err)
      }
    }
  }
}

const websocketUtils = new WebSocketUtils()

export default websocketUtils

引用:

再main.js中引入并挂载

import webSocketUtil from '@/utils/webSocketUtil';

app.config.globalProperties.$webSocketUtil = webSocketUtil;

在所需页面打开连接,并监听数据返回

//监听消息
const handleWsMsg= (res) => {
  console.log('========handleWsMsg=========',res);
}


proxy.$webSocketUtil.connectSocketInit('wss://xxxxxxxxx')
proxy.$webSocketUtil.exportMessage(handleWsMsg)


//关闭连接
if(proxy.$webSocketUtil.socketTask){
  proxy.$webSocketUtil.closeSocket()
}