37 lines
1.5 KiB
JavaScript
37 lines
1.5 KiB
JavaScript
export function connectWs(onMessage, opts = {}) {
|
|
let ws, retry = 0, closed = false;
|
|
function open() {
|
|
const proto = location.protocol === 'https:' ? 'wss' : 'ws';
|
|
const params = new URLSearchParams();
|
|
if (opts.room) params.set('room', opts.room);
|
|
if (opts.kind) params.set('kind', opts.kind);
|
|
const qs = params.toString();
|
|
ws = new WebSocket(`${proto}://${location.host}/ws${qs ? '?' + qs : ''}`);
|
|
ws.addEventListener('open', () => { retry = 0; opts.onOpen?.(); });
|
|
ws.addEventListener('message', (ev) => {
|
|
try { onMessage(JSON.parse(ev.data)); } catch { }
|
|
});
|
|
ws.addEventListener('close', () => {
|
|
opts.onClose?.();
|
|
if (closed) return;
|
|
retry = Math.min(retry + 1, 6);
|
|
setTimeout(open, 500 * 2 ** retry);
|
|
});
|
|
ws.addEventListener('error', () => ws.close());
|
|
}
|
|
open();
|
|
return {
|
|
// Returns true when the message was actually queued on a live socket,
|
|
// false when the socket is closing/reconnecting. Callers that need to
|
|
// surface a transport failure (transport buttons) inspect the result;
|
|
// fire-and-forget callers can ignore it.
|
|
send(msg) {
|
|
if (ws?.readyState !== WebSocket.OPEN) return false;
|
|
ws.send(JSON.stringify(msg));
|
|
return true;
|
|
},
|
|
close() { closed = true; ws?.close(); },
|
|
get readyState() { return ws?.readyState; }
|
|
};
|
|
}
|