class ChatService { constructor() { this.ws = null this.listeners = [] this.reconnectTimer = null this.connected = false this.connecting = false this.pendingMessages = [] } connect() { if (this.ws && this.ws.readyState === WebSocket.OPEN) return if (this.connecting) return this.connecting = true var token = localStorage.getItem('token') if (!token) { this.connecting = false return } var protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:' var host = window.location.host var wsUrl = protocol + '//' + host + '/ws/chat?token=' + token try { this.ws = new WebSocket(wsUrl) } catch (e) { this.connecting = false return } var self = this this.ws.onopen = function() { self.connected = true self.connecting = false clearTimeout(self.reconnectTimer) self.pendingMessages.forEach(function(msg) { self.ws.send(JSON.stringify(msg)) }) self.pendingMessages = [] } this.ws.onmessage = function(event) { try { var data = JSON.parse(event.data) self.listeners.forEach(function(cb) { cb(data) }) } catch (e) {} } this.ws.onclose = function() { self.connected = false self.connecting = false self.reconnectTimer = setTimeout(function() { self.connect() }, 3000) } this.ws.onerror = function() {} } send(data) { if (this.ws && this.ws.readyState === WebSocket.CONNECTING) { this.pendingMessages.push(data) return true } if (this.ws && this.ws.readyState === WebSocket.OPEN) { this.ws.send(JSON.stringify(data)) return true } this.pendingMessages.push(data) this.connect() return true } onMessage(callback) { var self = this this.listeners.push(callback) return function() { self.listeners = self.listeners.filter(function(cb) { return cb !== callback }) } } disconnect() { clearTimeout(this.reconnectTimer) if (this.ws) { this.ws.close() this.ws = null } this.connected = false this.connecting = false this.pendingMessages = [] } } var chatService = new ChatService() export { chatService }