记录-vue2中websocket即时通讯小工具封装

857 阅读2分钟

最初项目只有一个websocket实例,就从掘友处借鉴(deepcopy)了一份代码,十分愉快的结束了项目中植入websocket的需求任务,具体使用场景可参考链接处。
但是时隔一周后,后端队友提出了新一轮的想法,要在该页面加入第二个websocket,emmmm,经过我测试,之前愉快的移植并不能满足目前的场景了,本着学习进步(实在是没找到一个可以完美deepcopy的地方),就只能自己进行一下封装了。废话不多说,无图看真相

本次封装任务需求原则:
1、开箱即用,使用者所写代码尽量简洁
2、支持单页面/多页面多个socket实例同时存在

🎈代码部分

1、socket封装处,在需要使用的地方引入该js文件即可
utils/socket.js

*
 * @Author: yjt
 * @Date: 2023-11-14 17:14:36
 * @LastEditors:yjt
 * @LastEditTime: 2023-12-20 15:25:14
 * @FilePath:
 * @Description:
 *              Websocket 支持多实例化已挂载到vue实例上
 *              调用: this.$socket.initWebSocket(url, callback)
 *              单个注销: this.$socket.closeWebSocket(url)
 *              全部注销: this.$socket.closeAllWebSockets()
 */
import { Message } from 'element-ui'

class WebSocketService {
    constructor() {
        this.webSockets = {} // 存储WebSocket实例
    }
    /**
     * 初始化websocket
     * @param {*} url socket地址
     * @param {*} callback 回调函数
     */
    initWebSocket(url, callback) {
        const websocketUrl = url.replace('http://', 'ws://')
        if (callback && typeof callback !== 'function') {
            throw new Error('callback is not a function')
        }
        if ('WebSocket' in window) {
            const socket = new WebSocket(websocketUrl)
            socket.onopen = () => this.webSocketOpen(socket)
            socket.onmessage = (event) => this.webSocketOnMessage(event, socket)
            socket.onclose = (event) => this.webSocketOnClose(event, socket)
            socket.onerror = (error) => this.webSocketOnError(error, socket)

            this.webSockets[url] = {
                socket,
                callback,
                isConnect: true, // socket连接状态
                heartbeatTime: 60 * 1000 // 心跳监测时间
            }
        } else {
            return Message.error('该浏览器不支持 WebSocket!')
        }
    }

  webSocketOpen = (socket) => {
      console.log('WebSocket连接成功')
      const entry = this.findEntryBySocket(socket)
      if (entry) {
          this.startHeartbeat(socket, entry.heartbeatTime)
          entry.reConnectNum = 0
      }
  }

  webSocketOnMessage = (event, socket) => {
      //   console.log('WebSocket接收到消息:', event.data)
      const entry = this.findEntryBySocket(socket)
      if (entry) {
          const { callback } = entry
          const data = JSON.parse(event.data)
          callback({ res: data, isConnect: entry.isConnect })
      }
  }

  webSocketOnClose = (event, socket) => {
      const entry = this.findEntryBySocket(socket)
      if (entry) {
          this.stopHeartbeat(socket)
          entry.isConnect = false
          const { callback } = entry
          callback({ isConnect: entry.isConnect })
          //   console.log(`WebSocket已关闭 (code:${event.code})`)
          if (event.code === 1006) {
              if (entry.reConnectNum < 3) {
                  this.initWebSocket(entry.url, entry.callback)
                  entry.reConnectNum++
              } else {
                  Message.error('WebSocket连接不上,请刷新页面或联系开发人员!')
              }
          }
      }
  }

  webSocketOnError = (error, socket) => {
      const entry = this.findEntryBySocket(socket)
      if (entry) {
          this.stopHeartbeat(socket)
          entry.isConnect = false
          const { callback } = entry
          callback({ isConnect: entry.isConnect })
          console.error('WebSocket连接发生错误:', error)
      }
  }

  webSocketSend = (socket, data) => {
      if (socket.readyState === WebSocket.OPEN) {
          socket.send(JSON.stringify(data))
      } else {
          console.error('WebSocket连接未打开')
      }
  }

  startHeartbeat = (socket, heartbeatTime) => {
      socket.heartbeatTimer = setInterval(() => {
          this.webSocketSend(socket, { heartbeat: true })
      }, heartbeatTime)
  }

  stopHeartbeat = (socket) => {
      clearInterval(socket.heartbeatTimer)
  }

  closeWebSocket = (url) => {
      console.log('WebSocket连接关闭')
      const entry = this.webSockets[url]
      if (entry) {
          const { socket } = entry
          socket.close()
          delete this.webSockets[url] // 从存储中移除WebSocket实例
          this.stopHeartbeat(socket)
          entry.reConnectNum = 0
      }
  }
  closeAllWebSockets = () => {
      console.log('关闭所有WebSocket连接')
      Object.values(this.webSockets).forEach((entry) => {
          const { socket } = entry
          socket.close()
      })
      this.webSockets = {} // 清空存储的WebSocket实例
  }
  findEntryBySocket = (socket) => {
      const entries = Object.values(this.webSockets)
      return entries.find((entry) => entry.socket === socket)
  }
}

export default new WebSocketService()

2、挂载到原型,方便全局随处使用
main.js

import SocketService from '@/utils/socket'
Vue.prototype.$socket = SocketService

3、使用处
某个vue文件

mounted() {
     this.$socket.initWebSocket(url1, this.getDataBenData)
     this.$socket.initWebSocket(url2, this.getAlarmData)
},
beforeDestroy() {
     this.$socket.closeWebSocket(url) //单个关闭连接
     this.$socket.closeAllWebSockets() // 关闭全部socket连接
},
methods: {  
    getDataBenData({ res, isConnect }) {
        //获取第一个socket消息
    },
    getAlarmData({res,isConnect}){
        //获取第二个socket消息
    }

最后

如果觉得对您有所帮助可以给个关注和star~~~~如果有问题也可以留言交流