实现消息注册和回调函数,实现全局使用同一个webscoket对象,并实现断线重连和心跳连接等功能,可以实现全局使用唯一实例,可以另外进行拓展配置
// WebSocket类对象
class WebSocketCli {// 构造函数constructor(url: string, opts = {}) {this.url = urlthis.ws = nullthis.opts = {heartbeatInterval: 30000, // 默认30秒reconnectInterval: 5000, // 默认5秒maxReconnectAttempts: 5, // 默认尝试重连5次...opts,}this.heartbeatInterval = 30000this.reconnectAttempts = 0this.listeners = {}this.init()}// 链接地址url: string// websocket实例ws: WebSocket | null// websocket配置:配置心跳和重连等信息opts: any// 重新连接次数:默认5次reconnectAttempts: number// 时间监听对象数组:可以为一个事件绑定多个监听事件listeners: any// 心跳链接间隔heartbeatInterval: number | null// 初始化ws对象init() {this.ws = new WebSocket(this.url)this.ws.onopen = this.onOpen.bind(this)this.ws.onmessage = this.onMessage.bind(this)this.ws.onerror = this.onError.bind(this)this.ws.onclose = this.onClose.bind(this)}// websocket链接建立onOpen(event) {console.log('WebSocket opened:', event)this.reconnectAttempts = 0 // 重置重连次数// 发送心跳链接// this.startHeartbeat()this.emit('open', event)}// websocket收到消息onMessage(event) {console.log('WebSocket message received:', event.data)this.emit('message', event.data)}// websocket错误onError(event) {console.error('WebSocket error:', event)this.emit('error', event)}// websocket关闭onClose(event) {console.log('WebSocket closed:', event)// 停止心跳链接// this.stopHeartbeat()this.emit('close', event)// 最大5次重连if (this.reconnectAttempts < this.opts.maxReconnectAttempts) {setTimeout(() => {this.reconnectAttempts++this.init()}, this.opts.reconnectInterval)}}// 发送心跳startHeartbeat() {this.heartbeatInterval = setInterval(() => {if (this.ws?.readyState === WebSocket.OPEN) {this.ws.send('ping') // 可以修改为你的心跳消息格式}}, this.opts.heartbeatInterval)}// 停止心跳stopHeartbeat() {if (this.heartbeatInterval) {clearInterval(this.heartbeatInterval)this.heartbeatInterval = null}}// 发送消息send(data) {if (this.ws?.readyState === WebSocket.OPEN) {this.ws.send(data)} else {console.error('WebSocket is not open. Cannot send:', data)}}// 注册某个消息事件,并添加回调函数on(event, callback) {if (!this.listeners[event]) {this.listeners[event] = []}// 将回调函数放进事件数组中this.listeners[event].push(callback)}// 取消某个消息:如果存在回调函数就只移除这个回调事件,不存在就清空所有off(event, callback?) {if (!this.listeners[event]) returnconst index = callback && this.listeners[event].indexOf(callback)if (callback && index !== -1) {this.listeners[event].splice(index, 1)} else {console.log('移除所有事件: ', event)this.listeners[event] = []}}// 接收到消息后,通过这个函数执行所有回调函数emit(event, data) {if (this.listeners[event]) {this.listeners[event].forEach((callback) => callback(data))}}
}// 导出对象
export default WebSocketCli
使用的时候:单例模式
// 全局唯一websocket对象
const wsUrl = 'ws://192.168.1.171:9080/v1/server/webgetapi'
const wsInstance = new WebSocketCli(wsUrl)// 导出对象
export default wsInstance
vue使用的时候,需要注意:最好不要封装到自定义hooks里面,否则可能会出现注册后的消息为空的情况:然后就会导致消息监听失效