/** * WebSocket管理 * 管理WebSocket连接,处理WebSocket事件 */ class WebSocketManager { constructor(url = null) { this.url = url || this.getDefaultWebSocketUrl(); this.socket = null; this.isConnected = false; this.listeners = new Map(); this.reconnectAttempts = 0; this.maxReconnectAttempts = 5; this.reconnectDelay = 1000; } /** * 获取默认WebSocket URL * @returns {string} WebSocket URL */ getDefaultWebSocketUrl() { const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:'; return `${protocol}//${location.host}`; } /** * 连接WebSocket */ connect() { try { this.socket = new WebSocket(this.url); this.socket.onopen = () => { console.log('WebSocket connected'); this.isConnected = true; this.reconnectAttempts = 0; this.emit('connect'); }; this.socket.onclose = () => { console.log('WebSocket disconnected'); this.isConnected = false; this.emit('disconnect'); this.attemptReconnect(); }; this.socket.onmessage = (event) => { try { const message = JSON.parse(event.data); this.handleMessage(message); } catch (error) { console.error('Error parsing WebSocket message:', error); } }; this.socket.onerror = (error) => { console.error('WebSocket error:', error); this.emit('error', error); }; } catch (error) { console.error('Error connecting to WebSocket:', error); this.emit('error', error); } } /** * 断开WebSocket连接 */ disconnect() { if (this.socket) { this.socket.close(); this.socket = null; this.isConnected = false; } } /** * 发送消息 * @param {string} event - 事件名称 * @param {Object} data - 消息数据 */ send(event, data) { if (this.isConnected && this.socket) { try { const message = JSON.stringify({ event, data }); this.socket.send(message); } catch (error) { console.error('Error sending WebSocket message:', error); } } else { console.warn('WebSocket not connected, cannot send message'); } } /** * 处理接收到的消息 * @param {Object} message - 消息对象 */ handleMessage(message) { switch (message.type) { case 'user-joined': this.emit('user-joined', message.data); break; case 'user-left': this.emit('user-left', message.data); break; case 'media-state-changed': this.emit('media-state-changed', message.data); break; case 'message-received': this.emit('message-received', message.data); break; case 'network-quality': this.emit('network-quality', message.data); break; case 'call-ended': this.emit('call-ended', message.data); break; case 'ping': // 处理心跳请求,回复pong this.send('pong', {}); break; case 'pong': // 处理心跳响应 this.emit('pong'); break; default: this.emit('message', message); break; } } /** * 尝试重连 */ attemptReconnect() { if (this.reconnectAttempts < this.maxReconnectAttempts) { this.reconnectAttempts++; const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1); console.log(`Attempting to reconnect in ${delay}ms...`); setTimeout(() => { console.log(`Reconnect attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts}`); this.connect(); }, delay); } else { console.error('Max reconnect attempts reached'); this.emit('reconnect-failed'); } } /** * 订阅事件 * @param {string} event - 事件名称 * @param {Function} callback - 回调函数 */ on(event, callback) { if (!this.listeners.has(event)) { this.listeners.set(event, []); } this.listeners.get(event).push(callback); } /** * 取消订阅事件 * @param {string} event - 事件名称 * @param {Function} callback - 回调函数 */ off(event, callback) { if (this.listeners.has(event)) { const callbacks = this.listeners.get(event); this.listeners.set(event, callbacks.filter(cb => cb !== callback)); } } /** * 触发事件 * @param {string} event - 事件名称 * @param {*} data - 事件数据 */ emit(event, data) { if (this.listeners.has(event)) { this.listeners.get(event).forEach(callback => { try { callback(data); } catch (error) { console.error(`Error in event listener for ${event}:`, error); } }); } } /** * 检查连接状态 * @returns {boolean} 是否连接 */ getIsConnected() { return this.isConnected; } } // 创建单例实例 const wsManager = new WebSocketManager(); export default wsManager;