Files
dodep-simulator/static/js/websocket.js
T

94 lines
2.6 KiB
JavaScript

// WebSocket client for real-time features
const WS = {
_ws: null,
_reconnectTimer: null,
_listeners: {},
_connected: false,
connect() {
if (this._ws && this._ws.readyState === WebSocket.OPEN) return;
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
const url = `${protocol}//${window.location.host}/ws`;
try {
this._ws = new WebSocket(url);
} catch (e) {
console.warn('WS connection failed, retrying in 5s');
this._scheduleReconnect();
return;
}
this._ws.onopen = () => {
this._connected = true;
this._emit('connected');
};
this._ws.onclose = () => {
this._connected = false;
this._emit('disconnected');
this._scheduleReconnect();
};
this._ws.onerror = () => {
this._emit('error');
};
this._ws.onmessage = (event) => {
try {
const data = JSON.parse(event.data);
this._emit(data.type, data);
} catch (e) {
// ignore non-JSON messages
}
};
// Keepalive ping every 30s
this._pingInterval = setInterval(() => {
if (this._ws && this._ws.readyState === WebSocket.OPEN) {
this._ws.send(JSON.stringify({ type: 'ping' }));
}
}, 30000);
},
disconnect() {
if (this._pingInterval) clearInterval(this._pingInterval);
if (this._reconnectTimer) clearTimeout(this._reconnectTimer);
if (this._ws) {
this._ws.onclose = null;
this._ws.close();
this._ws = null;
}
this._connected = false;
},
_scheduleReconnect() {
if (this._reconnectTimer) return;
this._reconnectTimer = setTimeout(() => {
this._reconnectTimer = null;
this.connect();
}, 5000);
},
on(event, callback) {
if (!this._listeners[event]) this._listeners[event] = [];
this._listeners[event].push(callback);
return () => {
this._listeners[event] = this._listeners[event].filter(cb => cb !== callback);
};
},
_emit(event, data) {
(this._listeners[event] || []).forEach(cb => cb(data));
// Also emit all for catch-all listeners
(this._listeners['*'] || []).forEach(cb => cb(event, data));
},
isConnected() {
return this._connected;
}
};
// Auto-connect on page load
document.addEventListener('DOMContentLoaded', () => WS.connect());