import { ElMessage, EVENT_CODE } from 'element-plus' // 定义消息类型,用于类型检查 type MessageType = { [key: string]: any } export default class SocketService { // 单例模式实例 private static instance: SocketService | null = null // 和服务端连接的socket对象 private ws: WebSocket | null = null // 存储回调函数 private callBackMapping: { [key: string]: ((message: MessageType) => void) | null } = {} // 标识是否连接成功 private connected: boolean = false // 记录重试的次数 private sendRetryCount: number = 0 // 重新连接尝试的次数 private connectRetryCount: number = 0 // Web Worker 实例 private work: Worker | null = null // 临时的 Blob URL private workerBlobUrl: string | null = null // 上次活动时间戳 private lastActivityTime: number = 0 // 最后一次收到心跳回复时间 private lastResponseHeartTime: number = Date.now() // 重新连接延迟,单位毫秒 private reconnectDelay: number = 5000 // 单例模式获取实例 public static get Instance(): SocketService { if (!this.instance) { this.instance = new SocketService() } return this.instance } // 定义连接服务器的方法 public async connect(id: string) { if (!window.WebSocket) { console.log('您的浏览器不支持WebSocket') return } const response = await fetch('/') const mqttUrl = response.headers.get('X-Mqtt-Url') setTimeout(() => { const url = (mqttUrl || 'ws://192.168.1.31:10407/api/pushMessage/') + id this.ws = new WebSocket(url) this.ws.onopen = () => this.handleOpen() this.ws.onclose = () => this.handleClose() this.ws.onerror = () => this.handleError() this.ws.onmessage = event => this.handleMessage(event) }, 0) } // 处理连接成功事件 private handleOpen(): void { ElMessage.success('webSocket连接服务端成功了') console.log('连接服务端成功了') this.connected = true this.connectRetryCount = 0 this.updateLastActivityTime() this.startHeartbeat() } // 处理连接关闭事件 private handleClose(): void { console.log('连接webSocket服务端关闭') this.connected = false this.connectRetryCount++ this.clearHeartbeat() // 可根据需要添加重连逻辑 // setTimeout(() => this.connect(), 500 * this.connectRetryCount); } // 处理连接错误事件 private handleError(): void { ElMessage.error('webSocket连接异常!') } // 处理服务端发送过来的数据 private handleMessage(event: MessageEvent): void { // console.log('🚀 ~ SocketService ~ handleMessage ~ event.data:', event.data) if (event.data == '连接成功') { this.sendHeartbeat() } else if (event.data.length > 10) { let message: MessageType try { // console.log('Received message:', event.data) message = JSON.parse(event.data) } catch (e) { console.error('消息解析失败', event.data, e) return } // console.log("🚀 ~ SocketService ~ handleMessage ~ message:", message) // 通过接受服务端发送的type字段来回调函数 if (message.key && this.callBackMapping['message']) { this.callBackMapping['message']!(message) } else { console.log('抛弃====>') // console.log(event.data) // 丢弃或继续写你的逻辑 } } else { ElMessage.error(event.data) } } // 启动心跳检测 private startHeartbeat(): void { this.lastResponseHeartTime = Date.now() const url = window.URL.createObjectURL( new Blob(['(function(e){setInterval(function(){this.postMessage(null)},30000)})()']) ) this.workerBlobUrl = url this.work = new Worker(url) this.work.onmessage = e => this.handleWorkerMessage(e) } // 处理 Web Worker 消息 private handleWorkerMessage(e: MessageEvent): void { // if (this.lastActivityTime - this.lastResponseHeartTime > 30000) { // // 说明已经三轮心跳没收到回复了,关闭检测,提示用户。 // // ElMessage.error('业务主体模块发生未知异常,请尝试重新启动!') // this.clearHeartbeat() // return // } // console.log(123); this.sendHeartbeat() } // 发送心跳消息 private sendHeartbeat(): void { // console.log(new Date() + '进入心跳消息发送。。。。。。。。。。。。。') if (this.ws) { this.ws.send('alive') this.updateLastActivityTime() } } // 更新活动时间 private updateLastActivityTime(): void { this.lastActivityTime = Date.now() } // 清除心跳检测 private clearHeartbeat(): void { if (this.work) { this.work.terminate() this.work = null } if (this.workerBlobUrl) { window.URL.revokeObjectURL(this.workerBlobUrl) this.workerBlobUrl = null } } // 回调函数的注册 public registerCallBack(socketType: string, callBack: (message: MessageType) => void): void { this.callBackMapping[socketType] = callBack } // 取消某一个回调函数 public unRegisterCallBack(socketType: string): void { this.callBackMapping[socketType] = null } // 发送数据的方法 public send(data: any): void { if (this.connected) { this.sendRetryCount = 0 try { if (this.ws) { this.ws.send(JSON.stringify(data)) } } catch (e) { if (this.ws) { this.ws.send(data) } } } else { this.sendRetryCount++ setTimeout(() => this.send(data), this.sendRetryCount * 500) } } // 断开方法 public closeWs(): void { if (this.connected && this.ws) { this.ws.close() } console.log('执行WS关闭命令..') } }