// src/Service/Im/WebSocket.ts import { EventHandler } from '@/Service/Comm/EventHandler'; import { Service, ImConnectService } from '@/Service/Im/ImConnectService'; class WebSocketManager { private socketTask: UniApp.SocketTask | null = null; private heartbeatInterval: ReturnType | null = null; private readonly heartbeat: number = 30000; // 建议心跳30秒 private isConnecting: boolean = false; // 连接状态锁 private isUserClose: boolean = false; // 是否是用户主动关闭 public ConnectSocketInit(): void { if (this.isConnecting || this.socketTask) { console.warn('WebSocket 正在连接或已连接,请勿重复调用。'); return; } this.isConnecting = true; this.isUserClose = false; ImConnectService.GetConnect().then((res: any) => { if (res.code !== 0) { this.isConnecting = false; // Service.Msg('获取连接地址失败'); return; } Service.SetUserClientId(res.data.websocketId); this.socketTask = uni.connectSocket({ url: res.data.server, header: { 'content-type': 'application/json' }, // 推荐在小程序端开启 BSON // #ifdef MP-WEIXIN // protocols: ['bson'], // #endif success: () => {}, // success回调仅表示任务创建成功 }); // ✅ 绑定事件监听 (在 onOpen 外部) this.socketTask.onOpen(() => { console.log('==============WebSocket连接正常============='); this.isConnecting = false; this.startHeartbeat(); EventHandler.ConnectBus(); }); this.socketTask.onMessage((data: any) => { console.log('接收到消息'); EventHandler.Events(data); }); this.socketTask.onClose((e: any) => { console.log('========WebSocket连接已被关闭========', e); this.isConnecting = false; this.stopHeartbeat(); this.socketTask = null; // 清理实例 // 如果不是用户主动关闭,则触发重连 if (!this.isUserClose) { this.reconnect(); } }); this.socketTask.onError((err: any) => { console.error('========WebSocket连接发生错误========', err); this.isConnecting = false; // 错误发生时,通常也会触发 onClose,由 onClose 统一处理重连 }); }).catch(err => { this.isConnecting = false; console.error('GetConnect API 请求失败:', err); }); } private startHeartbeat(): void { this.stopHeartbeat(); // 先停止旧的,确保只有一个 const heartbeatData = JSON.stringify({ code: 'Heart', method: 'Heart' }); this.heartbeatInterval = setInterval(() => { console.log('======发送心跳检测======'); this.send(heartbeatData); }, this.heartbeat); } private stopHeartbeat(): void { if (this.heartbeatInterval) { clearInterval(this.heartbeatInterval); this.heartbeatInterval = null; } } // 重新连接 (带延迟和重试次数) public reconnect(): void { console.log('准备在3秒后尝试重连...'); setTimeout(() => { console.log('正在尝试重连...'); this.ConnectSocketInit(); // 在您的 EventHandler 或全局事件总线中可以增加重试次数限制 uni.$emit('ImReconnecting'); }, 3000); // 延迟3秒重连,避免频繁请求 } public CloseSocket(reason: string = 'user close'): void { if (!this.socketTask) return; this.isUserClose = true; this.stopHeartbeat(); // ✅ 立即停止心跳 this.socketTask.close({ code: 1000, reason: reason, success: () => { // ✅ 使用箭头函数 console.log('===============关闭 WebSocket 成功==================='); }, fail: (err) => { // ✅ 使用箭头函数 console.log('===================关闭 WebSocket 失败=====================', err); } }); } public send(value: any): void { if (this.socketTask && this.socketTask.readyState === 1) { // 检查连接状态 this.socketTask.send({ data: value, success: () => {}, // ✅ 使用箭头函数 fail: (err) => { // ✅ 使用箭头函数 console.error('发送消息失败:', err); // 发送失败通常意味着连接已断开,onClose会处理重连 } }); } else { console.error('WebSocket 未连接,无法发送消息。'); // 可以考虑将消息放入一个队列,等重连成功后再发送 } } } // 导出单例模式 export const WebSocket = new WebSocketManager();