You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
import { Subject } from "rxjs";
export type SocketState = "open" | "close" | "error";
class WebSocketClient { private ws: WebSocket | null = null; private url: string; private reconnectAttempts: number = -1; private maxReconnectAttempts: number = 5; private reconnectInterval: number = 3000;
private dataSub = new Subject<{ func: string; data: Record<string, any> | any[] }>(); get dataOb() { return this.dataSub.asObservable(); } private stateSub = new Subject<SocketState>(); get stateOb() { return this.stateSub.asObservable(); } constructor(url: string) { this.url = url; }
// 连接 WebSocket
connect(): void { try { // WebSocket.CONNECTING (0) WebSocket.OPEN (1)
if (this.ws && this.ws.readyState <= 1) { // 已连接
console.log(`${this.url} 正在连接或已连接,无需重复连接`); } else { this.ws = new WebSocket(this.url); this.bindEvents(); } localStorage.setItem('wsReadyState', `${this.ws.readyState}`) } catch (error) { console.error("WebSocket 连接失败:", error); this.reconnect(); } }
// 绑定事件
private bindEvents(): void { if (!this.ws) return;
// 连接建立时的处理
this.ws.onopen = () => { console.log("WebSocket 连接已建立"); this.reconnectAttempts = -1; // 重置重连次数
this.stateSub.next("open"); };
// 接收消息的处理
this.ws.onmessage = (event: MessageEvent) => { try { const data = JSON.parse(event.data) as { func: string; data: Record<string, any> | any[] }; // console.log("🚀 ~ WebSocketClient ~ bindEvents ~ data:", data);
// if (data.type === "cmd") {
// this.dataSub.next({ type: data.type, data: { ...data.data, success: data.data.status === "D0000" } });
// } else {
this.dataSub.next(data); // }
} catch (error) { console.error("消息解析错误:", error); } };
this.ws.onclose = () => { this.stateSub.next("close"); console.log("WebSocket 连接已关闭"); this.reconnect(); };
this.ws.onerror = error => { this.stateSub.next("error"); console.error("WebSocket 错误:", error); }; }
// 重连机制
private reconnect(): void { if (this.reconnectAttempts === -1) { this.reconnectAttempts = 0; } if (this.reconnectAttempts >= this.maxReconnectAttempts) { console.log("达到最大重连次数,停止重连"); this.reconnectAttempts = -1; return; }
setTimeout(() => { console.log(`尝试第 ${this.reconnectAttempts + 1} 次重连...`); this.reconnectAttempts++; this.connect(); }, this.reconnectInterval); }
// 关闭连接
disconnect(): void { if (this.ws) { this.ws.close(); this.ws = null; } } }
const urlSocketMap = new Map<string, WebSocketClient>();
// 导出 WebSocket 客户端
export const createWebSocket = (url: string): WebSocketClient => { if (urlSocketMap.has(url)) { return urlSocketMap.get(url)!; } else { const client = new WebSocketClient(url); urlSocketMap.set(url, client); return client; } };
export const sharedWsUrl = `ws://${process.env.REACT_APP_WS_URL}`;
|