使用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 ? ? ? ? ? } ? ? ? ? }) ? ? ? }, ? ? }
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。
查看更多关于vue3.0中使用websocket,封装到公共方法的实现的详细内容...
声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://www.haodehen.cn/did120230