// WebSocket 工具类 - 优化版 class WebsocketUtil { constructor(url, time, params) { this.url = url; this.params = params; this.time = time; this.socketTask = null; this.isOpen = false; this.isAppActive = true; // 应用是否活跃(前台) // 定时器相关 this.reconnectTimeout = null; this.heartbeatInterval = null; this.heartbeatTimeout = null; this.checkConnectionInterval = null; // 消息回调数组 this.messageCallbacks = []; // 重连策略配置 this.reconnectAttempts = 0; this.reconnectMaxAttempts = 5; this.reconnectDelay = 3000; this.maxReconnectDelay = 30000; // 事件监听器引用(用于销毁时移除) this.appShowListener = null; this.appHideListener = null; this.networkListener = null; this.visibilityChangeListener = null; // 初始化事件监听 this.initEventListeners(); // 初始化 WebSocket 连接 this.initializeWebSocket(); } // 初始化全局事件监听 initEventListeners() { // 1. 监听应用显示/隐藏(Uniapp 全局事件) this.appShowListener = uni.onAppShow(() => { console.log('应用从后台回到前台'); this.isAppActive = true; // 重置重连状态,立即尝试重连 this.resetReconnectState(); this.checkConnection(); this.startHeartbeat(); this.startConnectionCheck(); }); this.appHideListener = uni.onAppHide(() => { console.log('应用进入后台'); this.isAppActive = false; // 后台时暂停心跳和连接检查,避免无效重连 this.pauseHeartbeat(); this.pauseConnectionCheck(); }); // 2. 监听网络状态变化 this.networkListener = uni.onNetworkStatusChange((res) => { console.log('网络状态变化:', res); if (res.isConnected) { // 网络恢复,重置重连状态并立即重连 this.resetReconnectState(); this.checkConnection(); } }); // 3. 监听页面可见性变化(Web 端兼容) if (typeof document !== 'undefined') { this.visibilityChangeListener = () => { if (document.visibilityState === 'visible') { console.log('页面可见,激活连接'); this.isAppActive = true; this.resetReconnectState(); this.checkConnection(); this.startHeartbeat(); this.startConnectionCheck(); } else { console.log('页面隐藏,暂停连接活动'); this.isAppActive = false; this.pauseHeartbeat(); this.pauseConnectionCheck(); } }; document.addEventListener('visibilitychange', this.visibilityChangeListener); } } // 重置重连状态(用于应用前台切换、网络恢复时) resetReconnectState() { this.reconnectAttempts = 0; this.reconnectDelay = 3000; if (this.reconnectTimeout) { clearTimeout(this.reconnectTimeout); this.reconnectTimeout = null; } } // 初始化 WebSocket 连接 initializeWebSocket() { console.log('初始化WebSocket连接'); if (this.isOpen) return; // 关闭之前可能存在的连接 if (this.socketTask) { this.closeSocket(); } this.socketTask = uni.connectSocket({ url: this.url, success: () => { console.log('WebSocket连接请求发送成功'); }, fail: (error) => { console.error('WebSocket连接失败:', error); uni.$emit('is-socket-open', false); this.reconnect(); } }); // 连接打开事件 this.socketTask.onOpen((res) => { console.log('WebSocket连接正常!', res); this.isOpen = true; this.resetReconnectState(); // 重置重连状态 this.startHeartbeat(); this.listenForMessages(); uni.$emit('is-socket-open', true); }); // 连接错误事件 this.socketTask.onError((res) => { console.error('WebSocket连接错误:', res); uni.$emit('is-socket-open', false); this.reconnect(); }); // 连接关闭事件 this.socketTask.onClose((result) => { console.log('WebSocket连接已关闭:', result); this.isOpen = false; // 只有应用活跃时才重连 if (this.isAppActive) { this.reconnect(); } }); // 启动连接状态主动检查 this.startConnectionCheck(); } // 启动心跳检测(仅在应用活跃时) startHeartbeat() { if (!this.isAppActive) return; // 清除现有定时器 this.pauseHeartbeat(); this.heartbeatInterval = setInterval(() => { if (this.isOpen && this.isAppActive) { // 发送心跳包 this.send(JSON.stringify({ "type": "ping_interval", "set": "pad" })); // 5秒超时检测 this.heartbeatTimeout = setTimeout(() => { console.log('心跳超时,主动断开并重连'); this.closeSocket(); this.reconnect(); }, 5000); } }, this.time); } // 暂停心跳检测 pauseHeartbeat() { if (this.heartbeatInterval) { clearInterval(this.heartbeatInterval); this.heartbeatInterval = null; } if (this.heartbeatTimeout) { clearTimeout(this.heartbeatTimeout); this.heartbeatTimeout = null; } } // 启动连接状态主动检查(30秒一次) startConnectionCheck() { if (this.checkConnectionInterval) clearInterval(this.checkConnectionInterval); this.checkConnectionInterval = setInterval(() => { this.checkConnection(); }, 30000); } // 暂停连接状态检查 pauseConnectionCheck() { if (this.checkConnectionInterval) { clearInterval(this.checkConnectionInterval); this.checkConnectionInterval = null; } } // 主动检查连接状态 checkConnection() { if (this.isAppActive && !this.isOpen && !this.reconnectTimeout) { console.log('主动检查到连接断开,触发重连'); this.reconnect(); } } // 发送消息 send(data, type) { if (this.socketTask && this.isOpen) { this.socketTask.send({ data: data, success: () => { this.startHeartbeat(); // 发送成功重置心跳 }, fail: (error) => { console.error('消息发送失败:', error); this.reconnect(); } }); } else { console.warn('WebSocket未连接,无法发送消息'); } } // 监听 WebSocket 消息 listenForMessages() { if (this.socketTask) { this.socketTask.onMessage((res) => { const data = res.data.toString(); try { const message = JSON.parse(data); if (message.type === 'pong') { // 收到pong,清除心跳超时 if (this.heartbeatTimeout) clearTimeout(this.heartbeatTimeout); } } catch (e) { console.warn('消息解析失败(非JSON格式):', e); } // 触发外部回调 this.messageCallbacks.forEach(callback => callback(data)); }); } } // 重连 WebSocket(指数退避 + 应用活跃检测) reconnect() { // 应用在后台时,延迟重连 if (!this.isAppActive) { console.log('应用在后台,延迟重连'); return; } if (this.reconnectTimeout) clearTimeout(this.reconnectTimeout); // 达到最大重连次数,停止重试 if (this.reconnectAttempts >= this.reconnectMaxAttempts) { console.log(`已达最大重连次数 ${this.reconnectMaxAttempts},停止重连`); return; } // 指数退避延迟 const delay = Math.min( this.reconnectDelay * Math.pow(2, this.reconnectAttempts), this.maxReconnectDelay ); this.reconnectTimeout = setTimeout(() => { this.reconnectAttempts++; console.log(`重连尝试 ${this.reconnectAttempts}/${this.reconnectMaxAttempts},延迟 ${delay}ms`); this.initializeWebSocket(); }, delay); } // 关闭 WebSocket 连接 closeSocket() { if (this.socketTask) { uni.closeSocket({ success: () => { console.log('WebSocket连接已关闭'); this.isOpen = false; }, fail: (error) => { console.error('关闭WebSocket连接失败:', error); } }); this.socketTask = null; } } // 外部注册消息回调 onMessage(callback) { this.messageCallbacks.push(callback); } // 外部注销消息回调 offMessage(callback) { this.messageCallbacks = callback ? this.messageCallbacks.filter(cb => cb !== callback) : []; } // 销毁 WebSocket 连接,清理资源 destroy() { this.closeSocket(); // 清除所有定时器 this.pauseHeartbeat(); this.pauseConnectionCheck(); clearTimeout(this.reconnectTimeout); // 移除所有事件监听 if (this.appShowListener) uni.offAppShow(this.appShowListener); if (this.appHideListener) uni.offAppHide(this.appHideListener); if (this.networkListener) uni.offNetworkStatusChange(this.networkListener); if (this.visibilityChangeListener && typeof document !== 'undefined') { document.removeEventListener('visibilitychange', this.visibilityChangeListener); } // 清空回调数组 this.messageCallbacks = []; console.log('WebSocket资源已销毁'); } } export default WebsocketUtil;