185 lines
4.3 KiB
TypeScript
185 lines
4.3 KiB
TypeScript
/**
|
||
* WebSocket连接管理类
|
||
*/
|
||
export class WebSocketManager {
|
||
private ws: WebSocket | null = null;
|
||
private url: string;
|
||
private reconnectAttempts = 0;
|
||
private maxReconnectAttempts = 5;
|
||
private reconnectInterval = 3000;
|
||
private heartbeatInterval: NodeJS.Timeout | null = null;
|
||
private heartbeatTimer = 30000; // 30秒心跳
|
||
|
||
// 事件回调
|
||
private onMessageCallback?: (data: any) => void;
|
||
private onOpenCallback?: () => void;
|
||
private onCloseCallback?: () => void;
|
||
private onErrorCallback?: (error: Event) => void;
|
||
|
||
constructor(url: string) {
|
||
this.url = url;
|
||
}
|
||
|
||
/**
|
||
* 连接WebSocket
|
||
*/
|
||
connect(): Promise<void> {
|
||
return new Promise((resolve, reject) => {
|
||
try {
|
||
this.ws = new WebSocket(this.url);
|
||
|
||
this.ws.onopen = () => {
|
||
console.log('WebSocket连接成功');
|
||
this.reconnectAttempts = 0;
|
||
this.startHeartbeat();
|
||
this.onOpenCallback?.();
|
||
resolve();
|
||
};
|
||
|
||
this.ws.onmessage = (event) => {
|
||
try {
|
||
if(event.data !== '连接成功'){
|
||
const data = JSON.parse(event.data);
|
||
console.log(data,'data>>>')
|
||
this.onMessageCallback?.(data);
|
||
}
|
||
} catch (error) {
|
||
console.error('解析WebSocket消息失败:', error);
|
||
}
|
||
};
|
||
|
||
this.ws.onclose = () => {
|
||
console.log('WebSocket连接关闭');
|
||
this.stopHeartbeat();
|
||
this.onCloseCallback?.();
|
||
this.handleReconnect();
|
||
};
|
||
|
||
this.ws.onerror = (error) => {
|
||
console.error('WebSocket连接错误:', error);
|
||
this.onErrorCallback?.(error);
|
||
reject(error);
|
||
};
|
||
} catch (error) {
|
||
reject(error);
|
||
}
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 发送消息
|
||
*/
|
||
send(message: any): void {
|
||
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
||
this.ws.send(typeof message === 'string' ? message : JSON.stringify(message));
|
||
} else {
|
||
console.warn('WebSocket未连接,无法发送消息');
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 关闭连接
|
||
*/
|
||
close(): void {
|
||
this.stopHeartbeat();
|
||
if (this.ws) {
|
||
this.ws.close();
|
||
this.ws = null;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 重连处理
|
||
*/
|
||
private handleReconnect(): void {
|
||
if (this.reconnectAttempts < this.maxReconnectAttempts) {
|
||
this.reconnectAttempts++;
|
||
console.log(`尝试重连WebSocket (${this.reconnectAttempts}/${this.maxReconnectAttempts})`);
|
||
|
||
setTimeout(() => {
|
||
this.connect().catch(error => {
|
||
console.error('重连失败:', error);
|
||
// 继续尝试重连
|
||
this.handleReconnect();
|
||
});
|
||
}, this.reconnectInterval * this.reconnectAttempts); // 递增重连间隔
|
||
} else {
|
||
console.error('WebSocket重连次数已达上限');
|
||
// 重置重连次数,以便后续手动重连
|
||
setTimeout(() => {
|
||
this.reconnectAttempts = 0;
|
||
}, 60000); // 1分钟后重置
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 开始心跳
|
||
*/
|
||
private startHeartbeat(): void {
|
||
this.heartbeatInterval = setInterval(() => {
|
||
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
||
this.ws.send(JSON.stringify({ type: 'ping' }));
|
||
}
|
||
}, this.heartbeatTimer);
|
||
}
|
||
|
||
/**
|
||
* 停止心跳
|
||
*/
|
||
private stopHeartbeat(): void {
|
||
if (this.heartbeatInterval) {
|
||
clearInterval(this.heartbeatInterval);
|
||
this.heartbeatInterval = null;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 设置消息回调
|
||
*/
|
||
onMessage(callback: (data: any) => void): void {
|
||
this.onMessageCallback = callback;
|
||
}
|
||
|
||
/**
|
||
* 设置连接成功回调
|
||
*/
|
||
onOpen(callback: () => void): void {
|
||
this.onOpenCallback = callback;
|
||
}
|
||
|
||
/**
|
||
* 设置连接关闭回调
|
||
*/
|
||
onClose(callback: () => void): void {
|
||
this.onCloseCallback = callback;
|
||
}
|
||
|
||
/**
|
||
* 设置错误回调
|
||
*/
|
||
onError(callback: (error: Event) => void): void {
|
||
this.onErrorCallback = callback;
|
||
}
|
||
|
||
/**
|
||
* 获取连接状态
|
||
*/
|
||
getReadyState(): number {
|
||
return this.ws?.readyState ?? WebSocket.CLOSED;
|
||
}
|
||
|
||
/**
|
||
* 是否已连接
|
||
*/
|
||
isConnected(): boolean {
|
||
return this.ws?.readyState === WebSocket.OPEN;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 创建WebSocket连接
|
||
*/
|
||
export function createWebSocket(url: string): WebSocketManager {
|
||
return new WebSocketManager(url);
|
||
}
|