fix websocket reconnection with async conn.

This commit is contained in:
Miroslav Šedivý 2021-05-09 23:25:52 +02:00
parent f689bea219
commit 487114b3c8

View File

@ -2,8 +2,7 @@ import EventEmitter from 'eventemitter3'
import { Logger } from '../utils/logger' import { Logger } from '../utils/logger'
export const connTimeout = 15000 export const connTimeout = 15000
export const reconnTimeout = 1000 export const reconnInterval = 1000
export const reconnMultiplier = 1.2
export interface NekoWebSocketEvents { export interface NekoWebSocketEvents {
connecting: () => void connecting: () => void
@ -14,15 +13,12 @@ export interface NekoWebSocketEvents {
export class NekoWebSocket extends EventEmitter<NekoWebSocketEvents> { export class NekoWebSocket extends EventEmitter<NekoWebSocketEvents> {
private _ws?: WebSocket private _ws?: WebSocket
private _connTimer?: NodeJS.Timeout private _connTimer?: number
private _reconTimer?: number
private _log: Logger private _log: Logger
private _url: string private _url: string
private _token: string private _token: string
// reconnection
private _reconTimer?: NodeJS.Timeout
private _reconnTimeout: number = reconnTimeout
constructor() { constructor() {
super() super()
@ -82,7 +78,7 @@ export class NekoWebSocket extends EventEmitter<NekoWebSocketEvents> {
res() res()
} }
this._connTimer = setTimeout(rej.bind(this, new Error('connection timeout')), connTimeout) this._connTimer = window.setTimeout(rej.bind(this, new Error('connection timeout')), connTimeout)
}) })
} }
@ -90,7 +86,8 @@ export class NekoWebSocket extends EventEmitter<NekoWebSocketEvents> {
this.emit('disconnected', reason) this.emit('disconnected', reason)
if (this._connTimer) { if (this._connTimer) {
clearTimeout(this._connTimer) window.clearTimeout(this._connTimer)
this._connTimer = undefined
} }
if (typeof this._ws !== 'undefined') { if (typeof this._ws !== 'undefined') {
@ -118,14 +115,6 @@ export class NekoWebSocket extends EventEmitter<NekoWebSocketEvents> {
this._ws!.send(JSON.stringify({ event, ...payload })) this._ws!.send(JSON.stringify({ event, ...payload }))
} }
private tryReconnect() {
if (this._reconTimer) {
clearTimeout(this._reconTimer)
}
this._reconTimer = setTimeout(this.onReconnect.bind(this), this._reconnTimeout)
}
private onMessage(e: MessageEvent) { private onMessage(e: MessageEvent) {
const { event, ...payload } = JSON.parse(e.data) const { event, ...payload } = JSON.parse(e.data)
@ -135,11 +124,13 @@ export class NekoWebSocket extends EventEmitter<NekoWebSocketEvents> {
private onConnected() { private onConnected() {
if (this._connTimer) { if (this._connTimer) {
clearTimeout(this._connTimer) window.clearTimeout(this._connTimer)
this._connTimer = undefined
} }
if (this._reconTimer) { if (this._reconTimer) {
clearTimeout(this._reconTimer) window.clearInterval(this._reconTimer)
this._reconTimer = undefined
} }
if (!this.connected) { if (!this.connected) {
@ -149,21 +140,23 @@ export class NekoWebSocket extends EventEmitter<NekoWebSocketEvents> {
this._log.info(`connected`) this._log.info(`connected`)
this.emit('connected') this.emit('connected')
// reset reconnect timeout
this._reconnTimeout = reconnTimeout
} }
private onClose(reason: string) { private onClose(reason: string) {
this._log.info(`connection ${reason}`) this._log.info(`connection ${reason}`)
this.disconnect(new Error(`connection ${reason}`)) this.disconnect(new Error(`connection ${reason}`))
this.tryReconnect()
this._reconTimer = window.setInterval(async () => {
// connect only if disconnected
if (!this.connected) {
try {
await this.connect()
} catch (e) {
return
}
} }
private onReconnect() { window.clearInterval(this._reconTimer)
this._log.info(`reconnecting after ${this._reconnTimeout}ms`) }, reconnInterval)
this._reconnTimeout *= reconnMultiplier
this.connect()
} }
} }