import ReconnectingWebSocket from 'reconnecting-websocket'; import { getToken } from '../../storage'; type MessageHandler = (data: any) => void; class WSClient { private ws: ReconnectingWebSocket | null = null; private handler = new Set(); /** * Kết nối tới WebSocket server. * @param url Địa chỉ WebSocket server * @param isAuthenticated Có sử dụng token xác thực hay không */ connect(url: string, isAuthenticated: boolean) { if (this.ws) return; let token = ''; if (isAuthenticated) { token = getToken(); } const wsUrl = isAuthenticated ? `${url}?token=${token}` : url; this.ws = new ReconnectingWebSocket(wsUrl, [], { maxRetries: 10, maxReconnectionDelay: 10000, }); this.ws.onmessage = (event) => { try { const data = JSON.parse(event.data); this.handler.forEach((fn) => fn(data)); } catch (error) { console.error('WS Parse Error: ', error); } }; } /** * Ngắt kết nối WebSocket và giải phóng tài nguyên. */ disconnect() { this.ws?.close(); this.ws = null; } /** * Gửi dữ liệu qua WebSocket. * @param data Dữ liệu cần gửi (sẽ được stringify) */ send(data: any) { this.ws?.send(JSON.stringify(data)); } /** * Đăng ký callback để nhận dữ liệu từ WebSocket. * @param cb Hàm callback xử lý dữ liệu nhận được * @returns Hàm hủy đăng ký callback */ subscribe(cb: MessageHandler) { this.handler.add(cb); return () => this.handler.delete(cb); } /** * Kiểm tra trạng thái kết nối WebSocket. * @returns true nếu đã kết nối, ngược lại là false */ isConnected() { return this.ws?.readyState === WebSocket.OPEN; } } export const wsClient = new WSClient();