Files
TurboSu/static/js/ws.js
T
2026-07-25 15:23:40 +08:00

88 lines
2.3 KiB
JavaScript

const WS = {
_ws: null,
_url: '',
_reconnectTimer: null,
_reconnectDelay: 2000,
_handlers: {},
_connected: false,
init() {
const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
this._url = `${protocol}//${location.host}/ws`;
this._connect();
},
_connect() {
if (this._ws && this._ws.readyState === WebSocket.OPEN) return;
try {
this._ws = new WebSocket(this._url);
} catch (e) {
this._scheduleReconnect();
return;
}
this._ws.onopen = () => {
this._connected = true;
this._reconnectDelay = 2000;
this._emit('connection', true);
this._emit('status', 'connected');
};
this._ws.onmessage = (event) => {
try {
const msg = JSON.parse(event.data);
this._emit(msg.type || 'message', msg.data || msg);
if (msg.type === 'telemetry') {
this._emit('telemetry', msg.data);
}
} catch (e) {}
};
this._ws.onclose = () => {
this._connected = false;
this._emit('connection', false);
this._emit('status', 'disconnected');
this._scheduleReconnect();
};
this._ws.onerror = () => {
this._emit('status', 'error');
};
},
_scheduleReconnect() {
if (this._reconnectTimer) return;
this._reconnectTimer = setTimeout(() => {
this._reconnectTimer = null;
this._reconnectDelay = Math.min(this._reconnectDelay * 1.5, 10000);
this._connect();
}, this._reconnectDelay);
},
on(event, handler) {
if (!this._handlers[event]) this._handlers[event] = [];
this._handlers[event].push(handler);
},
off(event, handler) {
if (!this._handlers[event]) return;
this._handlers[event] = this._handlers[event].filter(h => h !== handler);
},
_emit(event, data) {
if (!this._handlers[event]) return;
this._handlers[event].forEach(h => h(data));
},
send(data) {
if (this._ws && this._ws.readyState === WebSocket.OPEN) {
this._ws.send(JSON.stringify(data));
}
},
get connected() { return this._connected; }
};
window.WS = WS;