最初项目只有一个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~~~~如果有问题也可以留言交流