| | |
| | | private maxReconnectAttempts: number = 5; |
| | | private reconnectTimer: any = null; |
| | | private heartbeatTimer: any = null; |
| | | private heartbeatInterval: number = 30000; // 30秒心跳 |
| | | private heartbeatTimeoutTimer: any = null; // 用于检测心跳超时的定时器 |
| | | private heartbeatInterval: number = 10000; // 10秒心跳 |
| | | private heartbeatTimeout: number = 3000; // 5秒收不到响应即视为掉线 |
| | | private listeners: Map<string, MessageCallback[]> = new Map(); |
| | | private globalEventsBound: boolean = false; |
| | | |
| | |
| | | this.socketTask.onOpen(async () => { |
| | | console.log('WebSocket 连接已打开'); |
| | | this.isConnected = true; |
| | | this.isConnecting = false; |
| | | this.reconnectAttempts = 0; |
| | | this.startHeartbeat(); |
| | | const uid = await getStorage(_UID) || '-1'; |
| | |
| | | |
| | | this.socketTask.onMessage((res) => { |
| | | try { |
| | | this.resetHeartbeatTimeout(); |
| | | const data = JSON.parse(res.data as string); |
| | | console.log('收到 WebSocket 消息:', res.data); |
| | | const content = JSON.parse(data.content || '{}'); |
| | |
| | | this.socketTask.onClose((res) => { |
| | | console.log('WebSocket 连接已关闭', res); |
| | | this.isConnected = false; |
| | | this.isConnecting = false; |
| | | this.stopHeartbeat(); |
| | | this.socketTask = null; |
| | | |
| | |
| | | this.socketTask.onError((err) => { |
| | | console.error('WebSocket 错误:', err); |
| | | this.isConnected = false; |
| | | this.isConnecting = false; |
| | | this.notifyListeners('error', err); |
| | | }); |
| | | return; |
| | |
| | | Taro.onSocketOpen(async () => { |
| | | console.log('WebSocket 连接已打开'); |
| | | this.isConnected = true; |
| | | this.isConnecting = false; |
| | | this.reconnectAttempts = 0; |
| | | this.startHeartbeat(); |
| | | const uid = await getStorage(_UID) || '-1'; |
| | |
| | | |
| | | Taro.onSocketMessage((res) => { |
| | | try { |
| | | this.resetHeartbeatTimeout(); |
| | | const data = JSON.parse(res.data as string); |
| | | console.log('收到 WebSocket 消息:', res.data); |
| | | const content = JSON.parse(data.content || '{}'); |
| | |
| | | Taro.onSocketClose((res) => { |
| | | console.log('WebSocket 连接已关闭', res); |
| | | this.isConnected = false; |
| | | this.isConnecting = false; |
| | | this.stopHeartbeat(); |
| | | this.socketTask = null; |
| | | |
| | |
| | | Taro.onSocketError((err) => { |
| | | console.error('WebSocket 错误:', err); |
| | | this.isConnected = false; |
| | | this.isConnecting = false; |
| | | this.notifyListeners('error', err); |
| | | }); |
| | | } |
| | |
| | | this.heartbeatTimer = setInterval(() => { |
| | | if (this.isConnected) { |
| | | this.send({ type: 'ping', timestamp: Date.now() }); |
| | | // 发送 ping 后,启动一个超时检测 |
| | | // 如果在配置的时间内没有收到任何消息(pong 或业务消息),则认为连接已假死 |
| | | if (this.heartbeatTimeoutTimer) { |
| | | clearTimeout(this.heartbeatTimeoutTimer); |
| | | } |
| | | this.heartbeatTimeoutTimer = setTimeout(() => { |
| | | console.warn('心跳超时,未收到服务器响应,主动断开 WebSocket 连接'); |
| | | this.closeAndReconnect(); |
| | | }, this.heartbeatTimeout); |
| | | } |
| | | }, this.heartbeatInterval); |
| | | } |
| | |
| | | clearInterval(this.heartbeatTimer); |
| | | this.heartbeatTimer = null; |
| | | } |
| | | if (this.heartbeatTimeoutTimer) { |
| | | clearTimeout(this.heartbeatTimeoutTimer); |
| | | this.heartbeatTimeoutTimer = null; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 收到消息时重置心跳超时检测 |
| | | */ |
| | | private resetHeartbeatTimeout() { |
| | | if (this.heartbeatTimeoutTimer) { |
| | | clearTimeout(this.heartbeatTimeoutTimer); |
| | | this.heartbeatTimeoutTimer = null; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 主动关闭并重连 (处理假死状态) |
| | | */ |
| | | private closeAndReconnect() { |
| | | // 强制关闭当前连接 |
| | | if (this.socketTask) { |
| | | try { |
| | | this.socketTask.close({ |
| | | code: 1000, |
| | | reason: '心跳超时主动关闭' |
| | | }); |
| | | } catch (e) { |
| | | console.error('强制关闭 Socket 失败:', e); |
| | | } |
| | | this.socketTask = null; |
| | | } |
| | | this.isConnected = false; |
| | | this.isConnecting = false; |
| | | this.stopHeartbeat(); |
| | | |
| | | // 立即触发重连 |
| | | if (!this.isManualClose) { |
| | | this.handleReconnect(); |
| | | } |
| | | } |
| | | |
| | | /** |