41 lines
1.1 KiB
JavaScript
41 lines
1.1 KiB
JavaScript
export class ReconnectingEventSource {
|
|
constructor(url, { retryDelayMs = 2000, maxRetryDelayMs = 15000 } = {}) {
|
|
this.url = url;
|
|
this.retryDelayMs = retryDelayMs;
|
|
this.maxRetryDelayMs = maxRetryDelayMs;
|
|
this.onmessage = null;
|
|
this.onerror = null;
|
|
this._closed = false;
|
|
this._es = null;
|
|
this._currentDelay = retryDelayMs;
|
|
this._connect();
|
|
}
|
|
|
|
_connect() {
|
|
if (this._closed) return;
|
|
this._es = new EventSource(this.url);
|
|
this._es.onmessage = (event) => {
|
|
this._currentDelay = this.retryDelayMs;
|
|
if (this.onmessage) this.onmessage(event);
|
|
};
|
|
this._es.onerror = (event) => {
|
|
if (this.onerror) this.onerror(event);
|
|
this._scheduleReconnect();
|
|
};
|
|
}
|
|
|
|
_scheduleReconnect() {
|
|
if (this._closed) return;
|
|
if (this._es) this._es.close();
|
|
const delay = this._currentDelay;
|
|
this._currentDelay = Math.min(this._currentDelay * 2, this.maxRetryDelayMs);
|
|
setTimeout(() => this._connect(), delay);
|
|
}
|
|
|
|
close() {
|
|
this._closed = true;
|
|
if (this._es) this._es.close();
|
|
this._es = null;
|
|
}
|
|
}
|