Files
webRtc/WebApp/client/public/onebyone/websocket.js
2026-03-03 17:51:30 +08:00

207 lines
5.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 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;