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: any) { if (!window.WebSocket) { console.log("您的浏览器不支持WebSocket"); return; } let response = null; if (import.meta.env.VITE_NAME == "beijing") { response = await fetch("/vue/"); } else if (import.meta.env.VITE_NAME == "wuxi") { response = await fetch(""); } // const response = await fetch("/vue/"); const mqttUrl = response.headers.get("X-Mqtt-Url"); console.log("🚀 ~ SocketService ~ connect ~ mqttUrl:", mqttUrl); setTimeout(() => { //"ws://10.156.193.182:18093/ws/screen" 北京 //"ws://192.168.1.130:19001/ws/askRealTimeData/" 无锡 const url = (mqttUrl || "ws://192.168.1.127:19001/ws/") + id; // const url = (mqttUrl || "ws://192.168.1.63:18093/ws/screen") + id; console.log("🚀 ~ SocketService ~ connect ~ url:", url); 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); this.callBackMapping["message"]!(message); } catch (e) { // console.error("消息解析失败", event.data, e); return; } // console.log("🚀 ~ SocketService ~ handleMessage ~ message:", message) // this.callBackMapping["message"]!(message); } 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关闭命令.."); } }