vue3.0中使用websocket,封装到公共方法的实现

使用websocket,封装到公共方法

首先创建一个socket.ts文件封装公共方法

/*
 * @Descripttion: 封装socket方法
 * @version:
 * @Date: 2021-08-06 11:14:39
 * @LastEditTime: 2021-10-26 14:06:34
 */
import i18n from '@/locales'
import store from '@/store'
import { ElMessage } from 'element-plus'
import { Base64 } from 'js-base64'
const language = store.state.users.language // 当前用户信息,后台配置
const token = store.state.users.authorization // 获取验证信息,后台配置
interface socket {
        websocket: any
        connectURL: string
        socket_open: boolean
        hearbeat_timer: any
        hearbeat_interval: number
        is_reonnect: boolean
        reconnect_count: number
        reconnect_current: number
        ronnect_number: number
        reconnect_timer: any
        reconnect_interval: number
        init: (receiveMessage: Function | null) => any
        receive: (message: any) => void
        heartbeat: () => void
        send: (data: any, callback?: any) => void
        close: () => void
        reconnect: () => void
}
const socket: socket = {
        websocket: null,
        connectURL: `${process.env.VUE_APP_SOCEKT_URL}/websocket/v1/${language}/${token}`,
        // 开启标识
        socket_open: false,
        // 心跳timer
        hearbeat_timer: null,
        // 心跳发送频率
        hearbeat_interval: 45000,
        // 是否自动重连
        is_reonnect: true,
        // 重连次数
        reconnect_count: 3,
        // 已发起重连次数
        reconnect_current: 1,
        // 网络错误提示此时
        ronnect_number: 0,
        // 重连timer
        reconnect_timer: null,
        // 重连频率
        reconnect_interval: 5000,
        init: (receiveMessage: Function | null) => {
                if (!('WebSocket' in window)) {
                        ElMessage.warning('浏览器不支持WebSocket')
                        return null
                }
                // 已经创建过连接不再重复创建
                // if (socket.websocket) {
                //   return socket.websocket
                // }
                socket.websocket = new WebSocket(socket.connectURL)
                socket.websocket.onmessage = (e: any) => {
                        if (receiveMessage) {
                                receiveMessage(e)
                        }
                }
                socket.websocket.onclose = (e: any) => {
                        clearInterval(socket.hearbeat_interval)
                        socket.socket_open = false
                        // 需要重新连接
                        if (socket.is_reonnect) {
                                socket.reconnect_timer = setTimeout(() => {
                                        // 超过重连次数
                                        if (socket.reconnect_current > socket.reconnect_count) {
                                                clearTimeout(socket.reconnect_timer)
                                                socket.is_reonnect = false
                                                return
                                        }
                                        // 记录重连次数
                                        socket.reconnect_current++
                                        socket.reconnect()
                                }, socket.reconnect_interval)
                        }
                }
                // 连接成功
                socket.websocket.onopen = function() {
                        socket.socket_open = true
                        socket.is_reonnect = true
                        // 开启心跳
                        // socket.heartbeat()
                }
                // 连接发生错误
                socket.websocket.onerror = function() {}
        },
        send: (data, callback = null) => {
                // 开启状态直接发送
                if (socket.websocket.readyState === socket.websocket.OPEN) {
                        socket.websocket.send(JSON.stringify(data))
                        if (callback) {
                                callback()
                        }
                        // 正在开启状态,则等待1s后重新调用
                } else {
                        clearInterval(socket.hearbeat_timer)
                        if (socket.ronnect_number < 1) {
                                ElMessage({
                                        type: 'error',
                                        message: i18n.global.t('chat.unopen'),
                                        duration: 0,
                                })
                        }
                        socket.ronnect_number++
                }
        },
        receive: (message: any) => {
                let params = Base64.decode(JSON.parse(message.data).data)
                params = JSON.parse(params)
                return params
        },
        heartbeat: () => {
                if (socket.hearbeat_timer) {
                        clearInterval(socket.hearbeat_timer)
                }
                socket.hearbeat_timer = setInterval(() => {
                        let data = {
                                languageId: store.state.users.language,
                                authToken: store.state.users.authorization,
                                content: 'ping',
                        }
                        var sendDara = {
                                encryption_type: 'base64',
                                data: Base64.encode(JSON.stringify(data)),
                        }
                        socket.send(sendDara)
                }, socket.hearbeat_interval)
        },
        close: () => {
                clearInterval(socket.hearbeat_interval)
                socket.is_reonnect = false
                socket.websocket.close()
        },
        /**
         * 重新连接
         */
        reconnect: () => {
                if (socket.websocket && !socket.is_reonnect) {
                        socket.close()
                }
                socket.init(null)
        },
}
export default socket

然后在聊天组件中引入

import socket from '@/utils/socket'

在挂载的生命周期放方法里面初始化socket

socket.init(methods.receiveMessage)

在这里 我们为websocket的onmessage方法传入了一个函数作为参数,这样的话我们在组件里面实现一个消息处理的方法

   // 消息接收
                        receiveMessage(message: any) {
                                const param = JSON.parse(Base64.decode(JSON.parse(message.data).data))
                                // 处理 赋值问题
                                const params = JSON.parse(JSON.stringify(param))
                                if (params) {
                                        switch (params.message) {
                                                case 'scheduleListFeedBack':
                                                        break
                                                case 'onMessage':
                                                        // 地磁获取消息列表 正则替换给过来的编码
                                        
                                                        break
                                        }
                                }
                        },

这样在onmessage里面的消息内容,我们可以通过方法传递回来,就可以在页面里面使用,其中的scheduleListFeedBack、onMessage是和后端定义的websocket的特定消息响应类型标识,可以拿到我们所需要的消息内容,进行逻辑处理。

这个方法是在socket.ts里面预先定义好的

socket.websocket.onmessage = (e: any) => {
        if (receiveMessage) {
                        receiveMessage(e)
                }
}

vue中封装websocket问题

每个组件页面都用到websocket,可以讲websocket封装起来,用到的组件页面一调用就好。

1.在untils文件夹下新建socket_service.js

export default class SocketService {
  static instance = null
  static get Instance () {
    if (!this.instance) {
      this.instance = new SocketService()
    }
    return this.instance
  }
  
  ws = null
  //存储回调函数
  callBackMapping = {}
  //标识是否连接成功
  connected = false
  //记录重试的次数
  sendRetryCount = 0
  //记录重新连接的次数
  reconnectCount = 0
  connect () {
    if (!window.WebSocket) {
      return console.log("您的浏览器不支持websocket!")
    }
    this.ws = new WebSocket('ws://192.168.0.88:8088')
    //连接服务端成功事件
    this.ws.onopen = ()=> {
      console.log("连接服务端成功")
      this.connected = true
      this.reconnectCount = 0
    }
    //连接服务端失败事件
    this.ws.onclose = ()=> {
      console.log("连接服务端失败")
      this.connected = false
      this.reconnectCount++
      setTimeout(()=>{
        this.connect()
      },this.reconnectCount*500)
    }
    //从服务端获取数据
    this.ws.onmessage = (msg)=> {
      console.log("从服务端获取到的数据" + msg.data)
      const recvData = JSON.parse(msg.data)
      const socketType = recvData.socketType
      if (this.callBackMapping[socketType]) {
        const action = recvData.action
        if (action === 'getData') {
          const realData = JSON.parse(recvData.data)
          this.callBackMapping[socketType].call(this, realData)
        }
      }
    }
  }
  //回调函数的注册
  registerCallBack (socketType, callBack) {
    this.callBackMapping[socketType] = callBack
  }
  //取消回调函数
  unRegisterCallBack (socketType) {
    this.callBackMapping[socketType] = null
  }
  send(data) {
    if (this.connected) {
      this.sendRetryCount = 0
      this.ws.send(JSON.stringify(data))
    } else {
      this.sendRetryCount++
      setTimeout(()=>{
        this.ws.send(JSON.stringify(data))
      },this.sendRetryCount*500)
    }
  } 
}

2.在main.js里引用

import SocketService from '@/utils/socket_service'
SocketService.Instance.connect()
Vue.prototype.$socket = SocketService.Instance
Vue.prototype.wsPath = 'ws://192.168.0.88:8088/'     // websocket路径

2.在组件里调用$socket

mounted() {
     this.$socket.send({
        action:'getData',
        socketType:'productivity',
        chartName:'product',
        value:''
      })
    },
created() {
      this.$socket.registerCallBack('productivity',this.getWsData)
    },
destroyed() {
     this.$socket.unRegisterCallBack('productivity')
    },
methods:{
    getWsData (ret) {
        console.log('websocket接收到的值', event.ret)
        console.log(ret);
        this.cdata.category.forEach(item => {
          if (dataRec.materialClassifyName === item.materialClassifyName) {
            item.rate = dataRec.rate
          }
        })
      },
    }

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

原文地址:https://blog.csdn.net/tj310/article/details/122298622