export type MessageHandler<T = any> = (data: T, timestamp: number) => void;
export class SimpleWebSocket {
private ws: WebSocket | null = null;
private reconnectAttempts = 0;
private isManualClose = false;
public isConnected = false;
public lastMessageTime = 0;
private onMessage?: MessageHandler;
private onOpen?: () => void;
private onClose?: () => void;
private onError?: (error: Event) => void;
private reconnectInterval: number;
private maxReconnectAttempts: number;
private url: string;
constructor(
url: string,
options: {
onMessage?: MessageHandler;
onOpen?: () => void;
onClose?: () => void;
onError?: (error: Event) => void;
reconnectInterval?: number;
maxReconnectAttempts?: number;
} = {}
) {
this.url = url;
this.onMessage = options.onMessage;
this.onOpen = options.onOpen;
this.onClose = options.onClose;
this.onError = options.onError;
this.reconnectInterval = options.reconnectInterval || 5000;
this.maxReconnectAttempts = options.maxReconnectAttempts || 5;
this.connect();
}
private connect() {
try {
this.ws = new WebSocket(this.url);
this.ws.onopen = () => {
this.isConnected = true;
this.reconnectAttempts = 0;
this.onOpen?.();
};
this.ws.onmessage = (event) => {
try {
const data = JSON.parse(event.data);
const timestamp = Date.now();
this.lastMessageTime = timestamp;
this.onMessage?.(data, timestamp);
} catch (error) {
console.error("[ChatChannel] 解析消息失败:", error);
this.onMessage?.(event.data, Date.now());
}
};
this.ws.onclose = () => {
this.isConnected = false;
this.onClose?.();
if (!this.isManualClose && this.reconnectAttempts < this.maxReconnectAttempts) {
setTimeout(() => {
this.reconnectAttempts++;
console.log(`[ChatChannel] 尝试重连 (${this.reconnectAttempts})`);
this.connect();
}, this.reconnectInterval);
}
};
this.ws.onerror = (error) => {
console.error("[ChatChannel] 连接错误:", error);
this.onError?.(error);
};
} catch (error) {
console.error("[ChatChannel] 连接失败:", error);
}
}
public disconnect() {
this.isManualClose = true;
if (this.ws) {
this.ws.close();
this.ws = null;
}
}
public send(data: any) {
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
this.ws.send(typeof data === "string" ? data : JSON.stringify(data));
} else {
console.warn("[ChatChannel] 未连接");
}
}
public reconnect() {
this.disconnect();
this.isManualClose = false;
this.reconnectAttempts = 0;
this.connect();
}
}