@cloudbase/realtime 1.2.3-alpha.0 → 1.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,12 @@
1
- import { VirtualWebSocketClient } from './virtual-websocket-client'
2
- import { genRequestId } from './message'
1
+ /* eslint-disable no-plusplus */
2
+ /* eslint-disable @typescript-eslint/consistent-type-assertions */
3
+ /* eslint-disable new-cap */
4
+ /* eslint-disable @typescript-eslint/no-misused-promises */
5
+ import { VirtualWebSocketClient } from './virtual-websocket-client';
6
+ import { genRequestId } from './message';
3
7
  import {
4
8
  IDatabaseServiceContext,
5
- } from '@cloudbase/types/database'
9
+ } from '@cloudbase/types/database';
6
10
  import {
7
11
  IWatchOptions,
8
12
  DBRealtimeListener,
@@ -11,17 +15,17 @@ import {
11
15
  IRequestMessagePingMsg,
12
16
  IRequestMessageLoginMsg,
13
17
  IResponseMessageLoginResMsg,
14
- IRequestMessageLoginData
15
- } from '@cloudbase/types/realtime'
18
+ IRequestMessageLoginData,
19
+ } from '@cloudbase/types/realtime';
16
20
  import {
17
21
  CLOSE_EVENT_CODE,
18
22
  CLOSE_EVENT_CODE_INFO,
19
- getWSCloseError
20
- } from './ws-event'
23
+ getWSCloseError,
24
+ } from './ws-event';
21
25
 
22
- import { ERR_CODE, TimeoutError, RealtimeErrorMessageError,CloudSDKError } from './error'
23
- import { getWsClass, getRuntime } from './common'
24
- import { sleep } from './utils'
26
+ import { ERR_CODE, TimeoutError, RealtimeErrorMessageError, CloudSDKError } from './error';
27
+ import { getWsClass, getRuntime } from './common';
28
+ import { sleep } from './utils';
25
29
 
26
30
  export interface IRealtimeWebSocketClientConstructorOptions {
27
31
  maxReconnect?: number
@@ -85,215 +89,203 @@ const WS_READY_STATE = {
85
89
  CONNECTING: 0,
86
90
  OPEN: 1,
87
91
  CLOSING: 2,
88
- CLOSED: 3
89
- }
90
-
91
- const MAX_RTT_OBSERVED = 3
92
- const DEFAULT_EXPECTED_EVENT_WAIT_TIME = 5000
93
- const DEFAULT_UNTRUSTED_RTT_THRESHOLD = 10000
94
- const DEFAULT_MAX_RECONNECT = 5
95
- const DEFAULT_WS_RECONNECT_INTERVAL = 10000
92
+ CLOSED: 3,
93
+ };
94
+
95
+ const MAX_RTT_OBSERVED = 3;
96
+ const DEFAULT_EXPECTED_EVENT_WAIT_TIME = 5000;
97
+ const DEFAULT_UNTRUSTED_RTT_THRESHOLD = 10000;
98
+ const DEFAULT_MAX_RECONNECT = 5;
99
+ const DEFAULT_WS_RECONNECT_INTERVAL = 10000;
96
100
  // const DEFAULT_WS_RECONNECT_MAX_VALID_INTERVAL = 3 * 60 * 1000
97
- const DEFAULT_PING_FAIL_TOLERANCE = 2
98
- const DEFAULT_PONG_MISS_TOLERANCE = 2
99
- const DEFAULT_LOGIN_TIMEOUT = 5000
101
+ const DEFAULT_PING_FAIL_TOLERANCE = 2;
102
+ const DEFAULT_PONG_MISS_TOLERANCE = 2;
103
+ const DEFAULT_LOGIN_TIMEOUT = 5000;
100
104
 
101
105
  export class RealtimeWebSocketClient {
102
- private _virtualWSClient: Set<VirtualWebSocketClient> = new Set()
106
+ private _virtualWSClient: Set<VirtualWebSocketClient> = new Set();
103
107
  // after listener initWatch, the listener has the queryID and can store it here
104
- private _queryIdClientMap: Map<string, VirtualWebSocketClient> = new Map()
105
- private _watchIdClientMap: Map<string, VirtualWebSocketClient> = new Map()
106
- private _maxReconnect: number
108
+ private _queryIdClientMap: Map<string, VirtualWebSocketClient> = new Map();
109
+ private _watchIdClientMap: Map<string, VirtualWebSocketClient> = new Map();
110
+ private _maxReconnect: number;
107
111
  // private _availableRetries: number
108
- private _reconnectInterval: number
109
- private _context: IDatabaseServiceContext
112
+ private _reconnectInterval: number;
113
+ private _context: IDatabaseServiceContext;
110
114
  // private _ws?: WXNS.Socket.ISocketTask
111
- private _ws?: any
112
- private _lastPingSendTS?: number
113
- private _pingFailed = 0
114
- private _pongMissed = 0
115
- private _pingTimeoutId?: number
116
- private _pongTimeoutId?: number
117
- private _logins: Map<string /* envId */, ILoginInfo> = new Map()
115
+ private _ws?: any;
116
+ private _lastPingSendTS?: number;
117
+ private _pingFailed = 0;
118
+ private _pongMissed = 0;
119
+ private _pingTimeoutId?: number;
120
+ private _pongTimeoutId?: number;
121
+ private _logins: Map<string /* envId */, ILoginInfo> = new Map();
118
122
  // private _loginInfo: ILoginInfo
119
123
  // private _signatures: Map<string /* envId */, ISignature> = new Map()
120
- private _wsInitPromise?: Promise<void>
121
- private _wsReadySubsribers: IResolveReject[] = []
124
+ private _wsInitPromise?: Promise<void>;
125
+ private _wsReadySubsribers: IResolveReject[] = [];
122
126
  private _wsResponseWait: Map<
123
- string /* requestId */,
124
- IResponseWaitSpec
125
- > = new Map()
126
- private _rttObserved: number[] = []
127
- private _reconnectState: boolean
127
+ string /* requestId */,
128
+ IResponseWaitSpec
129
+ > = new Map();
130
+ private _rttObserved: number[] = [];
131
+ private _reconnectState: boolean;
128
132
  // obtained from the first getSignature with no envId provided
129
133
  // private _defaultEnvId?: string
130
- private _wsSign: IWsSign
134
+ private _wsSign: IWsSign;
131
135
 
132
136
  constructor(options: IRealtimeWebSocketClientConstructorOptions) {
133
- this._maxReconnect = options.maxReconnect || DEFAULT_MAX_RECONNECT
137
+ this._maxReconnect = options.maxReconnect || DEFAULT_MAX_RECONNECT;
134
138
  // this._availableRetries = this._maxReconnect
135
- this._reconnectInterval =
136
- options.reconnectInterval || DEFAULT_WS_RECONNECT_INTERVAL
137
- this._context = options.context
139
+ this._reconnectInterval = options.reconnectInterval || DEFAULT_WS_RECONNECT_INTERVAL;
140
+ this._context = options.context;
138
141
  }
139
142
 
140
143
  clearHeartbeat() {
141
- this._pingTimeoutId && clearTimeout(this._pingTimeoutId)
142
- this._pongTimeoutId && clearTimeout(this._pongTimeoutId)
144
+ this._pingTimeoutId && clearTimeout(this._pingTimeoutId);
145
+ this._pongTimeoutId && clearTimeout(this._pongTimeoutId);
143
146
  }
144
147
 
145
- send = async <T = any>(opts: IWSSendOptions): Promise<T> =>
146
- new Promise<T>(async (_resolve, _reject) => {
147
- let timeoutId: number
148
- let _hasResolved = false
149
- let _hasRejected = false
150
-
151
- const resolve: typeof _resolve = (
152
- value?: T | PromiseLike<T> | undefined
153
- ) => {
154
- _hasResolved = true
155
- timeoutId && clearTimeout(timeoutId)
156
- _resolve(value)
157
- }
158
-
159
- const reject: typeof _reject = (error: any) => {
160
- _hasRejected = true
161
- timeoutId && clearTimeout(timeoutId)
162
- _reject(error)
163
- }
164
-
165
- if (opts.timeout) {
166
- // @ts-ignore
167
- timeoutId = setTimeout(async () => {
148
+ send = async <T = any>(opts: IWSSendOptions): Promise<T> => new Promise<T>(async (_resolve, _reject) => {
149
+ let timeoutId: number;
150
+ let _hasResolved = false;
151
+ let _hasRejected = false;
152
+
153
+ const resolve: typeof _resolve = (value?: T | PromiseLike<T> | undefined) => {
154
+ _hasResolved = true;
155
+ timeoutId && clearTimeout(timeoutId);
156
+ _resolve(value);
157
+ };
158
+
159
+ const reject: typeof _reject = (error: any) => {
160
+ _hasRejected = true;
161
+ timeoutId && clearTimeout(timeoutId);
162
+ _reject(error);
163
+ };
164
+
165
+ if (opts.timeout) {
166
+ // @ts-ignore
167
+ timeoutId = setTimeout(async () => {
168
+ if (!_hasResolved || !_hasRejected) {
169
+ // wait another immediate timeout to allow the success/fail callback to be invoked if ws has already got the result,
170
+ // this is because the timer is registered before ws.send
171
+ await sleep(0);
168
172
  if (!_hasResolved || !_hasRejected) {
169
- // wait another immediate timeout to allow the success/fail callback to be invoked if ws has already got the result,
170
- // this is because the timer is registered before ws.send
171
- await sleep(0)
172
- if (!_hasResolved || !_hasRejected) {
173
- reject(new TimeoutError('wsclient.send timedout'))
174
- }
173
+ reject(new TimeoutError('wsclient.send timedout'));
175
174
  }
176
- }, opts.timeout)
177
- }
175
+ }
176
+ }, opts.timeout);
177
+ }
178
178
 
179
- try {
180
- // if (this._context.debug) {
181
- // console.log(`[realtime] ws send (${new Date()}): `, opts)
182
- // console.log(
183
- // `[realtime] ws send ${
184
- // opts.msg.msgType
185
- // } (${new Date().toLocaleString()}): `,
186
- // opts
187
- // )
188
- // }
179
+ try {
180
+ // if (this._context.debug) {
181
+ // console.log(`[realtime] ws send (${new Date()}): `, opts)
182
+ // console.log(
183
+ // `[realtime] ws send ${
184
+ // opts.msg.msgType
185
+ // } (${new Date().toLocaleString()}): `,
186
+ // opts
187
+ // )
188
+ // }
189
+
190
+ if (this._wsInitPromise) {
191
+ await this._wsInitPromise;
192
+ }
189
193
 
190
- if (this._wsInitPromise) {
191
- await this._wsInitPromise
192
- }
194
+ if (!this._ws) {
195
+ reject(new Error('invalid state: ws connection not exists, can not send message'));
196
+ return;
197
+ }
193
198
 
194
- if (!this._ws) {
195
- reject(
196
- new Error(
197
- 'invalid state: ws connection not exists, can not send message'
198
- )
199
- )
200
- return
201
- }
199
+ if (this._ws.readyState !== WS_READY_STATE.OPEN) {
200
+ reject(new Error(`ws readyState invalid: ${this._ws.readyState}, can not send message`));
201
+ return;
202
+ }
202
203
 
203
- if (this._ws.readyState !== WS_READY_STATE.OPEN) {
204
- reject(
205
- new Error(
206
- `ws readyState invalid: ${this._ws.readyState}, can not send message`
207
- )
208
- )
209
- return
210
- }
204
+ if (opts.waitResponse) {
205
+ this._wsResponseWait.set(opts.msg.requestId, {
206
+ resolve,
207
+ reject,
208
+ skipOnMessage: opts.skipOnMessage,
209
+ } as IResponseWaitSpec);
210
+ }
211
211
 
212
- if (opts.waitResponse) {
213
- this._wsResponseWait.set(opts.msg.requestId, {
214
- resolve,
215
- reject,
216
- skipOnMessage: opts.skipOnMessage
217
- } as IResponseWaitSpec)
212
+ // console.log('send msg:', opts.msg)
213
+ try {
214
+ await this._ws.send(JSON.stringify(opts.msg));
215
+ if (!opts.waitResponse) {
216
+ resolve(undefined);
218
217
  }
219
-
220
- // console.log('send msg:', opts.msg)
221
- try {
222
- await this._ws.send(JSON.stringify(opts.msg))
223
- if (!opts.waitResponse) {
224
- resolve()
225
- }
226
- } catch (err) {
227
- if (err) {
228
- reject(err)
229
- if (opts.waitResponse) {
230
- this._wsResponseWait.delete(opts.msg.requestId)
231
- }
218
+ } catch (err) {
219
+ if (err) {
220
+ reject(err);
221
+ if (opts.waitResponse) {
222
+ this._wsResponseWait.delete(opts.msg.requestId);
232
223
  }
233
224
  }
234
- // this._ws.send(JSON.stringify(opts.msg), err => {
235
- // if (err) {
236
- // reject(err)
237
- // if (opts.waitResponse) {
238
- // this._wsResponseWait.delete(opts.msg.requestId)
239
- // }
240
- // return
241
- // }
242
-
243
- // if (!opts.waitResponse) {
244
- // resolve()
245
- // }
246
- // })
247
-
248
- // this._ws.send({
249
- // data: JSON.stringify(opts.msg),
250
- // success: res => {
251
- // if (!opts.waitResponse) {
252
- // resolve(res)
253
- // }
254
- // },
255
- // fail: e => {
256
- // reject(e)
257
- // if (opts.waitResponse) {
258
- // this._wsResponseWait.delete(opts.msg.requestId)
259
- // }
260
- // }
261
- // })
262
- } catch (e) {
263
- reject(e)
264
225
  }
265
- })
226
+ // this._ws.send(JSON.stringify(opts.msg), err => {
227
+ // if (err) {
228
+ // reject(err)
229
+ // if (opts.waitResponse) {
230
+ // this._wsResponseWait.delete(opts.msg.requestId)
231
+ // }
232
+ // return
233
+ // }
234
+
235
+ // if (!opts.waitResponse) {
236
+ // resolve()
237
+ // }
238
+ // })
239
+
240
+ // this._ws.send({
241
+ // data: JSON.stringify(opts.msg),
242
+ // success: res => {
243
+ // if (!opts.waitResponse) {
244
+ // resolve(res)
245
+ // }
246
+ // },
247
+ // fail: e => {
248
+ // reject(e)
249
+ // if (opts.waitResponse) {
250
+ // this._wsResponseWait.delete(opts.msg.requestId)
251
+ // }
252
+ // }
253
+ // })
254
+ } catch (e) {
255
+ reject(e);
256
+ }
257
+ });
266
258
 
267
259
  close(code: CLOSE_EVENT_CODE) {
268
- this.clearHeartbeat()
260
+ this.clearHeartbeat();
269
261
 
270
262
  if (this._ws) {
271
- this._ws.close(code, CLOSE_EVENT_CODE_INFO[code].name)
272
- this._ws = undefined
263
+ this._ws.close(code, CLOSE_EVENT_CODE_INFO[code].name);
264
+ this._ws = undefined;
273
265
  }
274
266
  }
275
267
 
276
268
  closeAllClients = (error: any) => {
277
- this._virtualWSClient.forEach(client => {
278
- client.closeWithError(error)
279
- })
280
- }
269
+ this._virtualWSClient.forEach((client) => {
270
+ client.closeWithError(error);
271
+ });
272
+ };
281
273
 
282
274
  pauseClients = (clients?: Set<VirtualWebSocketClient>) => {
283
- ;(clients || this._virtualWSClient).forEach(client => {
284
- client.pause()
285
- })
286
- }
275
+ (clients || this._virtualWSClient).forEach((client) => {
276
+ client.pause();
277
+ });
278
+ };
287
279
 
288
280
  resumeClients = (clients?: Set<VirtualWebSocketClient>) => {
289
- ;(clients || this._virtualWSClient).forEach(client => {
290
- client.resume()
291
- })
292
- }
281
+ (clients || this._virtualWSClient).forEach((client) => {
282
+ client.resume();
283
+ });
284
+ };
293
285
 
294
286
  watch(options: IWSWatchOptions): DBRealtimeListener {
295
287
  if (!this._ws && !this._wsInitPromise) {
296
- this.initWebSocketConnection(false)
288
+ this.initWebSocketConnection(false);
297
289
  }
298
290
 
299
291
  const virtualClient = new VirtualWebSocketClient({
@@ -305,11 +297,11 @@ export class RealtimeWebSocketClient {
305
297
  getWaitExpectedTimeoutLength: this.getWaitExpectedTimeoutLength,
306
298
  onWatchStart: this.onWatchStart,
307
299
  onWatchClose: this.onWatchClose,
308
- debug: true
309
- })
310
- this._virtualWSClient.add(virtualClient)
311
- this._watchIdClientMap.set(virtualClient.watchId, virtualClient)
312
- return virtualClient.listener
300
+ debug: true,
301
+ });
302
+ this._virtualWSClient.add(virtualClient);
303
+ this._watchIdClientMap.set(virtualClient.watchId, virtualClient);
304
+ return virtualClient.listener;
313
305
  }
314
306
 
315
307
  private initWebSocketConnection = async (
@@ -318,16 +310,16 @@ export class RealtimeWebSocketClient {
318
310
  ): Promise<void> => {
319
311
  // 当前处于正在重连中的状态
320
312
  if (reconnect && this._reconnectState) {
321
- return // 忽略
313
+ return; // 忽略
322
314
  }
323
315
 
324
316
  if (reconnect) {
325
- this._reconnectState = true // 重连状态开始
317
+ this._reconnectState = true; // 重连状态开始
326
318
  }
327
319
 
328
320
  if (this._wsInitPromise) {
329
321
  // there already exists a websocket initiation, just wait for it
330
- return this._wsInitPromise
322
+ return this._wsInitPromise;
331
323
  }
332
324
 
333
325
  // if (process.env.DEBUG) {
@@ -337,10 +329,10 @@ export class RealtimeWebSocketClient {
337
329
  // }
338
330
 
339
331
  if (reconnect) {
340
- this.pauseClients()
332
+ this.pauseClients();
341
333
  }
342
334
 
343
- this.close(CLOSE_EVENT_CODE.ReconnectWebSocket)
335
+ this.close(CLOSE_EVENT_CODE.ReconnectWebSocket);
344
336
 
345
337
  this._wsInitPromise = new Promise<void>(async (resolve, reject) => {
346
338
  try {
@@ -358,14 +350,14 @@ export class RealtimeWebSocketClient {
358
350
  // }
359
351
 
360
352
  // const signature = await this.getSignature()
361
- const wsSign = await this.getWsSign()
353
+ const wsSign = await this.getWsSign();
362
354
 
363
355
  // if (process.env.DEBUG) {
364
356
  // console.log('[realtime] initWebSocketConnection getSignature success')
365
357
  // console.log('[realtime] initWebSocketConnection start connectSocket')
366
358
  // }
367
359
 
368
- await new Promise(success => {
360
+ await new Promise((success) => {
369
361
  // this._ws = getSDK(this._context.identifiers)
370
362
  // ._socketSkipCheckDomainFactory()
371
363
  // .connectSocket({
@@ -379,12 +371,12 @@ export class RealtimeWebSocketClient {
379
371
 
380
372
  const url = wsSign.wsUrl || 'wss://tcb-ws.tencentcloudapi.com';
381
373
  const wsClass = getWsClass();
382
- this._ws = wsClass ? new wsClass(url) : new WebSocket(url)
383
- success()
384
- })
374
+ this._ws = wsClass ? new wsClass(url) : new WebSocket(url);
375
+ success(undefined);
376
+ });
385
377
 
386
- if(this._ws.connect){
387
- await this._ws.connect()
378
+ if (this._ws.connect) {
379
+ await this._ws.connect();
388
380
  }
389
381
 
390
382
  // if (process.env.DEBUG) {
@@ -393,23 +385,23 @@ export class RealtimeWebSocketClient {
393
385
  // )
394
386
  // }
395
387
 
396
- await this.initWebSocketEvent()
397
- resolve()
388
+ await this.initWebSocketEvent();
389
+ resolve();
398
390
 
399
391
  if (reconnect) {
400
- this.resumeClients()
401
- this._reconnectState = false // 重连状态结束
392
+ this.resumeClients();
393
+ this._reconnectState = false; // 重连状态结束
402
394
  }
403
395
  } catch (e) {
404
396
  // if (process.env.DEBUG) {
405
- console.error('[realtime] initWebSocketConnection connect fail', e)
397
+ console.error('[realtime] initWebSocketConnection connect fail', e);
406
398
  // }
407
399
 
408
400
  if (availableRetries > 0) {
409
401
  // this is an optimization, in case of network offline, we don't need to stubbornly sleep for sometime,
410
402
  // we only need to wait for the network to be back online, this ensures minimum downtime
411
403
  // const { isConnected } = await getNetworkStatus()
412
- const isConnected = true
404
+ const isConnected = true;
413
405
 
414
406
  // if (process.env.DEBUG) {
415
407
  // console.log(
@@ -430,7 +422,7 @@ export class RealtimeWebSocketClient {
430
422
  // console.log('[realtime] initWebSocketConnection network online')
431
423
  // }
432
424
 
433
- this._wsInitPromise = undefined
425
+ this._wsInitPromise = undefined;
434
426
 
435
427
  if (isConnected) {
436
428
  // if (process.env.DEBUG) {
@@ -438,39 +430,37 @@ export class RealtimeWebSocketClient {
438
430
  // `[realtime] initWebSocketConnection sleep ${this._reconnectInterval}ms`
439
431
  // )
440
432
  // }
441
- await sleep(this._reconnectInterval)
433
+ await sleep(this._reconnectInterval);
442
434
  if (reconnect) {
443
- this._reconnectState = false // 重连异常也算重连状态结束
435
+ this._reconnectState = false; // 重连异常也算重连状态结束
444
436
  }
445
437
  }
446
438
 
447
- resolve(this.initWebSocketConnection(reconnect, availableRetries - 1))
439
+ resolve(this.initWebSocketConnection(reconnect, availableRetries - 1));
448
440
  } else {
449
- reject(e)
441
+ reject(e);
450
442
 
451
443
  if (reconnect) {
452
- this.closeAllClients(
453
- new CloudSDKError({
454
- errCode: ERR_CODE.SDK_DATABASE_REALTIME_LISTENER_RECONNECT_WATCH_FAIL as string,
455
- errMsg: e
456
- })
457
- )
444
+ this.closeAllClients(new CloudSDKError({
445
+ errCode: ERR_CODE.SDK_DATABASE_REALTIME_LISTENER_RECONNECT_WATCH_FAIL as string,
446
+ errMsg: e,
447
+ }));
458
448
  }
459
449
  }
460
450
  }
461
- })
451
+ });
462
452
 
463
453
  // let success = false
464
454
 
465
455
  try {
466
- await this._wsInitPromise
456
+ await this._wsInitPromise;
467
457
  // success = true
468
- this._wsReadySubsribers.forEach(({ resolve }) => resolve())
458
+ this._wsReadySubsribers.forEach(({ resolve }) => resolve());
469
459
  } catch (e) {
470
- this._wsReadySubsribers.forEach(({ reject }) => reject())
460
+ this._wsReadySubsribers.forEach(({ reject }) => reject());
471
461
  } finally {
472
- this._wsInitPromise = undefined
473
- this._wsReadySubsribers = []
462
+ this._wsInitPromise = undefined;
463
+ this._wsReadySubsribers = [];
474
464
  }
475
465
 
476
466
  // if (process.env.DEBUG) {
@@ -478,264 +468,255 @@ export class RealtimeWebSocketClient {
478
468
  // `[realtime] initWebSocketConnection ${success ? 'success' : 'fail'}`
479
469
  // )
480
470
  // }
481
- }
482
-
483
- private initWebSocketEvent = () =>
484
- new Promise<void>((resolve, reject) => {
485
- if (!this._ws) {
486
- throw new Error('can not initWebSocketEvent, ws not exists')
487
- }
488
-
489
- let wsOpened = false
490
-
491
- this._ws.onopen = event => {
492
- // this._ws.onOpen(() => {
493
- // this._ws.on("open", () => {
494
- // this._context.debug &&
495
- console.warn('[realtime] ws event: open', event)
496
- wsOpened = true
497
- resolve()
498
- }
471
+ };
499
472
 
500
- this._ws.onerror = event => {
501
- // this._ws.on("error", error => {
502
- // this._ws.onError(error => {
503
- // all logins are invalid after disconnection
504
- this._logins = new Map()
473
+ private initWebSocketEvent = () => new Promise<void>((resolve, reject) => {
474
+ if (!this._ws) {
475
+ throw new Error('can not initWebSocketEvent, ws not exists');
476
+ }
505
477
 
506
- // error写进file
478
+ let wsOpened = false;
507
479
 
508
- if (!wsOpened) {
509
- // this._context.debug &&
510
- console.error('[realtime] ws open failed with ws event: error', event)
511
- // writeToFile(
512
- // "wserror.txt",
513
- // `${
514
- // this.specialNumber
515
- // } [realtime] ws open failed with ws event: error ${error} \n`
516
- // )
480
+ this._ws.onopen = (event) => {
481
+ // this._ws.onOpen(() => {
482
+ // this._ws.on("open", () => {
483
+ // this._context.debug &&
484
+ console.warn('[realtime] ws event: open', event);
485
+ wsOpened = true;
486
+ resolve();
487
+ };
517
488
 
518
- reject(event)
519
- } else {
520
- // this._context.debug &&
521
- console.error('[realtime] ws event: error', event)
489
+ this._ws.onerror = (event) => {
490
+ // this._ws.on("error", error => {
491
+ // this._ws.onError(error => {
492
+ // all logins are invalid after disconnection
493
+ this._logins = new Map();
522
494
 
523
- // writeToFile(
524
- // "wserror.txt",
525
- // `${this.specialNumber} [realtime] ws event: error ${error} \n`
526
- // )
527
-
528
- this.clearHeartbeat()
529
- this._virtualWSClient.forEach(client =>
530
- client.closeWithError(
531
- new CloudSDKError({
532
- errCode: ERR_CODE.SDK_DATABASE_REALTIME_LISTENER_WEBSOCKET_CONNECTION_ERROR as string,
533
- errMsg: event
534
- })
535
- )
536
- )
537
- }
538
- }
539
-
540
- // TODO: reconnect
541
- this._ws.onclose = closeEvent => {
542
- // this._ws.on("close", (closeEvent, closereason) => {
543
- // this._ws.onClose(closeEvent => {
544
- // if (process.env.DEBUG) {
545
- console.warn('[realtime] ws event: close', closeEvent)
546
- // }
495
+ // error写进file
547
496
 
497
+ if (!wsOpened) {
498
+ // this._context.debug &&
499
+ console.error('[realtime] ws open failed with ws event: error', event);
548
500
  // writeToFile(
549
- // "wsclose.txt",
501
+ // "wserror.txt",
550
502
  // `${
551
503
  // this.specialNumber
552
- // } [realtime] ws event: close ${closeEvent} ${closereason} \n`
504
+ // } [realtime] ws open failed with ws event: error ${error} \n`
553
505
  // )
554
506
 
555
- // all logins are invalid after disconnection
556
- this._logins = new Map()
507
+ reject(event);
508
+ } else {
509
+ // this._context.debug &&
510
+ console.error('[realtime] ws event: error', event);
557
511
 
558
- this.clearHeartbeat()
559
- switch (closeEvent.code) {
560
- case CLOSE_EVENT_CODE.ReconnectWebSocket: {
561
- // just ignore
562
- break
563
- }
564
- case CLOSE_EVENT_CODE.NoRealtimeListeners: {
565
- // quit
566
- break
567
- }
568
- case CLOSE_EVENT_CODE.HeartbeatPingError:
569
- case CLOSE_EVENT_CODE.HeartbeatPongTimeoutError:
570
- case CLOSE_EVENT_CODE.NormalClosure:
571
- case CLOSE_EVENT_CODE.AbnormalClosure: {
572
- // Normal Closure and Abnormal Closure:
573
- // expected closure, most likely dispatched by wechat client,
574
- // since this is the status code dispatched in case of network failure,
575
- // we should retry
576
-
577
- if (this._maxReconnect > 0) {
578
- // if (this._availableRetries > 0) {
579
- this.initWebSocketConnection(true, this._maxReconnect)
580
- } else {
581
- this.closeAllClients(getWSCloseError(closeEvent.code))
582
- }
583
- break
584
- }
585
- case CLOSE_EVENT_CODE.NoAuthentication: {
586
- this.closeAllClients(
587
- getWSCloseError(closeEvent.code, closeEvent.reason)
588
- )
589
- break
512
+ // writeToFile(
513
+ // "wserror.txt",
514
+ // `${this.specialNumber} [realtime] ws event: error ${error} \n`
515
+ // )
516
+
517
+ this.clearHeartbeat();
518
+ this._virtualWSClient.forEach(client => client.closeWithError(new CloudSDKError({
519
+ errCode: ERR_CODE.SDK_DATABASE_REALTIME_LISTENER_WEBSOCKET_CONNECTION_ERROR as string,
520
+ errMsg: event,
521
+ })));
522
+ }
523
+ };
524
+
525
+ // TODO: reconnect
526
+ this._ws.onclose = (closeEvent) => {
527
+ // this._ws.on("close", (closeEvent, closereason) => {
528
+ // this._ws.onClose(closeEvent => {
529
+ // if (process.env.DEBUG) {
530
+ console.warn('[realtime] ws event: close', closeEvent);
531
+ // }
532
+
533
+ // writeToFile(
534
+ // "wsclose.txt",
535
+ // `${
536
+ // this.specialNumber
537
+ // } [realtime] ws event: close ${closeEvent} ${closereason} \n`
538
+ // )
539
+
540
+ // all logins are invalid after disconnection
541
+ this._logins = new Map();
542
+
543
+ this.clearHeartbeat();
544
+ switch (closeEvent.code) {
545
+ case CLOSE_EVENT_CODE.ReconnectWebSocket: {
546
+ // just ignore
547
+ break;
548
+ }
549
+ case CLOSE_EVENT_CODE.NoRealtimeListeners: {
550
+ // quit
551
+ break;
552
+ }
553
+ case CLOSE_EVENT_CODE.HeartbeatPingError:
554
+ case CLOSE_EVENT_CODE.HeartbeatPongTimeoutError:
555
+ case CLOSE_EVENT_CODE.NormalClosure:
556
+ case CLOSE_EVENT_CODE.AbnormalClosure: {
557
+ // Normal Closure and Abnormal Closure:
558
+ // expected closure, most likely dispatched by wechat client,
559
+ // since this is the status code dispatched in case of network failure,
560
+ // we should retry
561
+
562
+ if (this._maxReconnect > 0) {
563
+ // if (this._availableRetries > 0) {
564
+ this.initWebSocketConnection(true, this._maxReconnect);
565
+ } else {
566
+ this.closeAllClients(getWSCloseError(closeEvent.code));
590
567
  }
591
- default: {
592
- // we should retry by default
593
- if (this._maxReconnect > 0) {
594
- // if (this._availableRetries > 0) {
595
- this.initWebSocketConnection(true, this._maxReconnect)
596
- } else {
597
- this.closeAllClients(getWSCloseError(closeEvent.code))
598
- }
599
- // console.warn(`[realtime] unrecognize ws close event`, closeEvent)
600
- // this.closeAllClients(getWSCloseError(closeEvent.code))
568
+ break;
569
+ }
570
+ case CLOSE_EVENT_CODE.NoAuthentication: {
571
+ this.closeAllClients(getWSCloseError(closeEvent.code, closeEvent.reason));
572
+ break;
573
+ }
574
+ default: {
575
+ // we should retry by default
576
+ if (this._maxReconnect > 0) {
577
+ // if (this._availableRetries > 0) {
578
+ this.initWebSocketConnection(true, this._maxReconnect);
579
+ } else {
580
+ this.closeAllClients(getWSCloseError(closeEvent.code));
601
581
  }
582
+ // console.warn(`[realtime] unrecognize ws close event`, closeEvent)
583
+ // this.closeAllClients(getWSCloseError(closeEvent.code))
602
584
  }
603
585
  }
586
+ };
604
587
 
605
- this._ws.onmessage = res => {
606
- // this._ws.on("message", res => {
607
- // this._ws.onMessage(res => {
608
- // const rawMsg = res.data
609
- const rawMsg = res.data
588
+ this._ws.onmessage = (res) => {
589
+ // this._ws.on("message", res => {
590
+ // this._ws.onMessage(res => {
591
+ // const rawMsg = res.data
592
+ const rawMsg = res.data;
610
593
 
611
- // reset & restart heartbeat
612
- this.heartbeat()
594
+ // reset & restart heartbeat
595
+ this.heartbeat();
613
596
 
614
- let msg: IResponseMessage
597
+ let msg: IResponseMessage;
615
598
 
616
- try {
617
- msg = JSON.parse(rawMsg as string)
618
- } catch (e) {
619
- throw new Error(`[realtime] onMessage parse res.data error: ${e}`)
620
- }
599
+ try {
600
+ msg = JSON.parse(rawMsg as string);
601
+ } catch (e) {
602
+ throw new Error(`[realtime] onMessage parse res.data error: ${e}`);
603
+ }
621
604
 
622
- // console.log(
623
- // `[realtime] onMessage ${
624
- // msg.msgType
625
- // } (${new Date().toLocaleString()})`,
626
- // msg
627
- // )
605
+ // console.log(
606
+ // `[realtime] onMessage ${
607
+ // msg.msgType
608
+ // } (${new Date().toLocaleString()})`,
609
+ // msg
610
+ // )
611
+
612
+ if (msg.msgType === 'ERROR') {
613
+ // 找到当前监听,并将error返回
614
+ let virtualWatch = null;
615
+ this._virtualWSClient.forEach((item) => {
616
+ if (item.watchId === msg.watchId) {
617
+ virtualWatch = item;
618
+ }
619
+ });
628
620
 
629
- if (msg.msgType === 'ERROR') {
630
- // 找到当前监听,并将error返回
631
- let virtualWatch = null
632
- this._virtualWSClient.forEach(item => {
633
- if (item.watchId === msg.watchId) {
634
- virtualWatch = item
635
- }
636
- })
621
+ if (virtualWatch) {
622
+ virtualWatch.listener.onError(msg);
623
+ }
624
+ }
637
625
 
638
- if (virtualWatch) {
639
- virtualWatch.listener.onError(msg)
626
+ const responseWaitSpec = this._wsResponseWait.get(msg.requestId);
627
+ if (responseWaitSpec) {
628
+ try {
629
+ if (msg.msgType === 'ERROR') {
630
+ responseWaitSpec.reject(new RealtimeErrorMessageError(msg));
631
+ } else {
632
+ responseWaitSpec.resolve(msg);
640
633
  }
634
+ } catch (e) {
635
+ // this._context.debug &&
636
+ console.error(
637
+ 'ws onMessage responseWaitSpec.resolve(msg) errored:',
638
+ e
639
+ );
640
+ } finally {
641
+ this._wsResponseWait.delete(msg.requestId);
642
+ }
643
+ if (responseWaitSpec.skipOnMessage) {
644
+ return;
641
645
  }
646
+ }
642
647
 
643
- const responseWaitSpec = this._wsResponseWait.get(msg.requestId)
644
- if (responseWaitSpec) {
645
- try {
646
- if (msg.msgType === 'ERROR') {
647
- responseWaitSpec.reject(new RealtimeErrorMessageError(msg))
648
- } else {
649
- responseWaitSpec.resolve(msg)
650
- }
651
- } catch (e) {
648
+ if (msg.msgType === 'PONG') {
649
+ if (this._lastPingSendTS) {
650
+ const rtt = Date.now() - this._lastPingSendTS;
651
+ if (rtt > DEFAULT_UNTRUSTED_RTT_THRESHOLD) {
652
652
  // this._context.debug &&
653
- console.error(
654
- 'ws onMessage responseWaitSpec.resolve(msg) errored:',
655
- e
656
- )
657
- } finally {
658
- this._wsResponseWait.delete(msg.requestId)
653
+ console.warn(`[realtime] untrusted rtt observed: ${rtt}`);
654
+ return;
659
655
  }
660
- if (responseWaitSpec.skipOnMessage) {
661
- return
656
+ if (this._rttObserved.length >= MAX_RTT_OBSERVED) {
657
+ this._rttObserved.splice(
658
+ 0,
659
+ this._rttObserved.length - MAX_RTT_OBSERVED + 1
660
+ );
662
661
  }
662
+ this._rttObserved.push(rtt);
663
663
  }
664
+ return;
665
+ }
664
666
 
665
- if (msg.msgType === 'PONG') {
666
- if (this._lastPingSendTS) {
667
- const rtt = Date.now() - this._lastPingSendTS
668
- if (rtt > DEFAULT_UNTRUSTED_RTT_THRESHOLD) {
669
- // this._context.debug &&
670
- console.warn(`[realtime] untrusted rtt observed: ${rtt}`)
671
- return
672
- }
673
- if (this._rttObserved.length >= MAX_RTT_OBSERVED) {
674
- this._rttObserved.splice(
675
- 0,
676
- this._rttObserved.length - MAX_RTT_OBSERVED + 1
677
- )
667
+ let client = msg.watchId && this._watchIdClientMap.get(msg.watchId);
668
+ if (client) {
669
+ client.onMessage(msg);
670
+ } else {
671
+ // TODO, this is a temporary fix done for server
672
+ // if (process.env.DEBUG) {
673
+ console.error(
674
+ `[realtime] no realtime listener found responsible for watchId ${msg.watchId}: `,
675
+ msg
676
+ );
677
+ // }
678
+ switch (msg.msgType) {
679
+ case 'INIT_EVENT':
680
+ case 'NEXT_EVENT':
681
+ case 'CHECK_EVENT': {
682
+ client = this._queryIdClientMap.get(msg.msgData.queryID);
683
+ if (client) {
684
+ client.onMessage(msg);
678
685
  }
679
- this._rttObserved.push(rtt)
686
+ break;
680
687
  }
681
- return
682
- }
683
-
684
- let client = msg.watchId && this._watchIdClientMap.get(msg.watchId)
685
- if (client) {
686
- client.onMessage(msg)
687
- } else {
688
- // TODO, this is a temporary fix done for server
689
- // if (process.env.DEBUG) {
690
- console.error(
691
- `[realtime] no realtime listener found responsible for watchId ${msg.watchId}: `,
692
- msg
693
- )
694
- // }
695
- switch (msg.msgType) {
696
- case 'INIT_EVENT':
697
- case 'NEXT_EVENT':
698
- case 'CHECK_EVENT': {
699
- client = this._queryIdClientMap.get(msg.msgData.queryID)
700
- if (client) {
701
- client.onMessage(msg)
702
- }
703
- break
704
- }
705
- default: {
706
- for (const [,client] of Array.from(this._watchIdClientMap.entries())) {
707
- // console.log('watchid*****', watchId)
708
- client.onMessage(msg)
709
- break
710
- }
688
+ default: {
689
+ for (const [,client] of Array.from(this._watchIdClientMap.entries())) {
690
+ // console.log('watchid*****', watchId)
691
+ client.onMessage(msg);
692
+ break;
711
693
  }
712
694
  }
713
695
  }
714
696
  }
697
+ };
715
698
 
716
- this.heartbeat()
717
- })
699
+ this.heartbeat();
700
+ });
718
701
 
719
- private isWSConnected = (): boolean => {
720
- return Boolean(this._ws && this._ws.readyState === WS_READY_STATE.OPEN)
721
- }
702
+ private isWSConnected = (): boolean => Boolean(this._ws && this._ws.readyState === WS_READY_STATE.OPEN);
722
703
 
723
704
  private onceWSConnected = async (): Promise<void> => {
724
705
  if (this.isWSConnected()) {
725
- return
706
+ return;
726
707
  }
727
708
 
728
709
  if (this._wsInitPromise) {
729
- return this._wsInitPromise
710
+ return this._wsInitPromise;
730
711
  }
731
712
 
732
713
  return new Promise<void>((resolve, reject) => {
733
714
  this._wsReadySubsribers.push({
734
715
  resolve,
735
- reject
736
- })
737
- })
738
- }
716
+ reject,
717
+ });
718
+ });
719
+ };
739
720
 
740
721
  private webLogin = async (
741
722
  envId?: string,
@@ -744,21 +725,21 @@ export class RealtimeWebSocketClient {
744
725
  if (!refresh) {
745
726
  // let loginInfo = this._loginInfo
746
727
  if (envId) {
747
- const loginInfo = this._logins.get(envId)
728
+ const loginInfo = this._logins.get(envId);
748
729
  if (loginInfo) {
749
730
  if (loginInfo.loggedIn && loginInfo.loginResult) {
750
731
  // if (process.env.DEBUG) {
751
732
  // console.log('[realtime] login: already logged in')
752
733
  // }
753
- return loginInfo.loginResult
754
- } else if (loginInfo.loggingInPromise) {
755
- return loginInfo.loggingInPromise
734
+ return loginInfo.loginResult;
735
+ } if (loginInfo.loggingInPromise) {
736
+ return loginInfo.loggingInPromise;
756
737
  }
757
738
  }
758
739
  } else {
759
- const emptyEnvLoginInfo = this._logins.get('')
740
+ const emptyEnvLoginInfo = this._logins.get('');
760
741
  if (emptyEnvLoginInfo?.loggingInPromise) {
761
- return emptyEnvLoginInfo.loggingInPromise
742
+ return emptyEnvLoginInfo.loggingInPromise;
762
743
  }
763
744
  }
764
745
  }
@@ -768,7 +749,7 @@ export class RealtimeWebSocketClient {
768
749
  try {
769
750
  // const signature = await this.getSignature(envId, refresh)
770
751
 
771
- const wsSign = await this.getWsSign()
752
+ const wsSign = await this.getWsSign();
772
753
 
773
754
  // const wxVersion = getWXVersion()
774
755
  const msgData: IRequestMessageLoginData = {
@@ -778,8 +759,8 @@ export class RealtimeWebSocketClient {
778
759
  // secretVersion: signature.secretVersion,
779
760
  referrer: 'web',
780
761
  sdkVersion: '',
781
- dataVersion: ''
782
- }
762
+ dataVersion: '',
763
+ };
783
764
  const loginMsg: IRequestMessageLoginMsg = {
784
765
  watchId: undefined,
785
766
  requestId: genRequestId(),
@@ -788,51 +769,47 @@ export class RealtimeWebSocketClient {
788
769
  exMsgData: {
789
770
  runtime: getRuntime(),
790
771
  signStr: wsSign.signStr,
791
- secretVersion: wsSign.secretVersion
792
- }
793
- }
772
+ secretVersion: wsSign.secretVersion,
773
+ },
774
+ };
794
775
  const loginResMsg = await this.send<IResponseMessageLoginResMsg>({
795
776
  msg: loginMsg,
796
777
  waitResponse: true,
797
778
  skipOnMessage: true,
798
- timeout: DEFAULT_LOGIN_TIMEOUT
799
- })
779
+ timeout: DEFAULT_LOGIN_TIMEOUT,
780
+ });
800
781
 
801
782
  if (!loginResMsg.msgData.code) {
802
783
  // login success
803
784
  resolve({
804
- envId: wsSign.envId
805
- })
785
+ envId: wsSign.envId,
786
+ });
806
787
  } else {
807
788
  // login failed
808
- reject(
809
- new Error(
810
- `${loginResMsg.msgData.code} ${loginResMsg.msgData.message}`
811
- )
812
- )
789
+ reject(new Error(`${loginResMsg.msgData.code} ${loginResMsg.msgData.message}`));
813
790
  }
814
791
  } catch (e) {
815
- reject(e)
792
+ reject(e);
816
793
  }
817
- })
794
+ });
818
795
 
819
796
  // let loginInfo = this._loginInfo
820
- let loginInfo = envId && this._logins.get(envId)
797
+ let loginInfo = envId && this._logins.get(envId);
821
798
 
822
- const loginStartTS = Date.now()
799
+ const loginStartTS = Date.now();
823
800
 
824
801
  if (loginInfo) {
825
- loginInfo.loggedIn = false
826
- loginInfo.loggingInPromise = promise
827
- loginInfo.loginStartTS = loginStartTS
802
+ loginInfo.loggedIn = false;
803
+ loginInfo.loggingInPromise = promise;
804
+ loginInfo.loginStartTS = loginStartTS;
828
805
  } else {
829
806
  loginInfo = {
830
807
  loggedIn: false,
831
808
  loggingInPromise: promise,
832
- loginStartTS
833
- }
809
+ loginStartTS,
810
+ };
834
811
  // this._loginInfo = loginInfo
835
- this._logins.set(envId || '', loginInfo)
812
+ this._logins.set(envId || '', loginInfo);
836
813
  }
837
814
 
838
815
  // try {
@@ -851,113 +828,111 @@ export class RealtimeWebSocketClient {
851
828
  // }
852
829
 
853
830
  try {
854
- const loginResult = await promise
855
- const curLoginInfo = envId && this._logins.get(envId)
831
+ const loginResult = await promise;
832
+ const curLoginInfo = envId && this._logins.get(envId);
856
833
  if (
857
- curLoginInfo &&
858
- curLoginInfo === loginInfo &&
859
- curLoginInfo.loginStartTS === loginStartTS
834
+ curLoginInfo
835
+ && curLoginInfo === loginInfo
836
+ && curLoginInfo.loginStartTS === loginStartTS
860
837
  ) {
861
- loginInfo.loggedIn = true
862
- loginInfo.loggingInPromise = undefined
863
- loginInfo.loginStartTS = undefined
864
- loginInfo.loginResult = loginResult
865
- return loginResult
866
- } else if (curLoginInfo) {
838
+ loginInfo.loggedIn = true;
839
+ loginInfo.loggingInPromise = undefined;
840
+ loginInfo.loginStartTS = undefined;
841
+ loginInfo.loginResult = loginResult;
842
+ return loginResult;
843
+ } if (curLoginInfo) {
867
844
  if (curLoginInfo.loggedIn && curLoginInfo.loginResult) {
868
- return curLoginInfo.loginResult
869
- } else if (curLoginInfo.loggingInPromise) {
870
- return curLoginInfo.loggingInPromise
871
- } else {
872
- throw new Error('ws unexpected login info')
845
+ return curLoginInfo.loginResult;
846
+ } if (curLoginInfo.loggingInPromise) {
847
+ return curLoginInfo.loggingInPromise;
873
848
  }
849
+ throw new Error('ws unexpected login info');
874
850
  } else {
875
- throw new Error('ws login info reset')
851
+ throw new Error('ws login info reset');
876
852
  }
877
853
  } catch (e) {
878
- loginInfo.loggedIn = false
879
- loginInfo.loggingInPromise = undefined
880
- loginInfo.loginStartTS = undefined
881
- loginInfo.loginResult = undefined
882
- throw e
854
+ loginInfo.loggedIn = false;
855
+ loginInfo.loggingInPromise = undefined;
856
+ loginInfo.loginStartTS = undefined;
857
+ loginInfo.loginResult = undefined;
858
+ throw e;
883
859
  }
884
- }
860
+ };
885
861
 
886
862
  private getWsSign = async (): Promise<IWsSign> => {
887
863
  if (this._wsSign && this._wsSign.expiredTs > Date.now()) {
888
- return this._wsSign
864
+ return this._wsSign;
889
865
  }
890
- const expiredTs = Date.now() + 60000
891
- const res = await this._context.appConfig.request.send('auth.wsWebSign', {runtime: getRuntime()})
866
+ const expiredTs = Date.now() + 60000;
867
+ const res = await this._context.appConfig.request.send('auth.wsWebSign', { runtime: getRuntime() });
892
868
 
893
869
  if (res.code) {
894
- throw new Error(`[tcb-js-sdk] 获取实时数据推送登录票据失败: ${res.code}`)
870
+ throw new Error(`[tcb-js-sdk] 获取实时数据推送登录票据失败: ${res.code}`);
895
871
  }
896
872
 
897
873
  if (res.data) {
898
- const {signStr, wsUrl, secretVersion, envId} = res.data
874
+ const { signStr, wsUrl, secretVersion, envId } = res.data;
899
875
  return {
900
876
  signStr,
901
877
  wsUrl,
902
878
  secretVersion,
903
879
  envId,
904
- expiredTs
905
- }
906
- } else {
907
- throw new Error('[tcb-js-sdk] 获取实时数据推送登录票据失败')
880
+ expiredTs,
881
+ };
908
882
  }
909
- }
883
+ throw new Error('[tcb-js-sdk] 获取实时数据推送登录票据失败');
884
+ };
910
885
 
911
886
  private getWaitExpectedTimeoutLength = () => {
912
887
  if (!this._rttObserved.length) {
913
- return DEFAULT_EXPECTED_EVENT_WAIT_TIME
888
+ return DEFAULT_EXPECTED_EVENT_WAIT_TIME;
914
889
  }
915
890
 
916
891
  // 1.5 * RTT
917
892
  return (
918
- (this._rttObserved.reduce((acc, cur) => acc + cur) /
919
- this._rttObserved.length) *
920
- 1.5
921
- )
922
- }
893
+ (this._rttObserved.reduce((acc, cur) => acc + cur)
894
+ / this._rttObserved.length)
895
+ * 1.5
896
+ );
897
+ };
923
898
 
924
899
  private heartbeat(immediate?: boolean) {
925
- this.clearHeartbeat()
900
+ this.clearHeartbeat();
926
901
  // @ts-ignore
927
902
  this._pingTimeoutId = setTimeout(
928
903
  async () => {
929
904
  try {
930
905
  if (!this._ws || this._ws.readyState !== WS_READY_STATE.OPEN) {
931
906
  // no need to ping
932
- return
907
+ return;
933
908
  }
934
909
 
935
- this._lastPingSendTS = Date.now()
936
- await this.ping()
937
- this._pingFailed = 0
910
+ this._lastPingSendTS = Date.now();
911
+ await this.ping();
912
+ this._pingFailed = 0;
938
913
 
939
914
  // @ts-ignore
940
915
  this._pongTimeoutId = setTimeout(() => {
941
- console.error('pong timed out')
916
+ console.error('pong timed out');
942
917
  if (this._pongMissed < DEFAULT_PONG_MISS_TOLERANCE) {
943
- this._pongMissed++
944
- this.heartbeat(true)
918
+ this._pongMissed++;
919
+ this.heartbeat(true);
945
920
  } else {
946
921
  // logical perceived connection lost, even though websocket did not receive error or close event
947
- this.initWebSocketConnection(true)
922
+ this.initWebSocketConnection(true);
948
923
  }
949
- }, this._context.appConfig.realtimePongWaitTimeout)
924
+ }, this._context.appConfig.realtimePongWaitTimeout);
950
925
  } catch (e) {
951
926
  if (this._pingFailed < DEFAULT_PING_FAIL_TOLERANCE) {
952
- this._pingFailed++
953
- this.heartbeat()
927
+ this._pingFailed++;
928
+ this.heartbeat();
954
929
  } else {
955
- this.close(CLOSE_EVENT_CODE.HeartbeatPingError)
930
+ this.close(CLOSE_EVENT_CODE.HeartbeatPingError);
956
931
  }
957
932
  }
958
933
  },
959
934
  immediate ? 0 : this._context.appConfig.realtimePingInterval
960
- )
935
+ );
961
936
  }
962
937
 
963
938
  private ping = async () => {
@@ -965,28 +940,28 @@ export class RealtimeWebSocketClient {
965
940
  watchId: undefined,
966
941
  requestId: genRequestId(),
967
942
  msgType: 'PING',
968
- msgData: null
969
- }
943
+ msgData: null,
944
+ };
970
945
  await this.send({
971
- msg
972
- })
946
+ msg,
947
+ });
973
948
  // console.log('ping sent')
974
- }
949
+ };
975
950
 
976
951
  private onWatchStart = (client: VirtualWebSocketClient, queryID: string) => {
977
- this._queryIdClientMap.set(queryID, client)
978
- }
952
+ this._queryIdClientMap.set(queryID, client);
953
+ };
979
954
 
980
955
  private onWatchClose = (client: VirtualWebSocketClient, queryID: string) => {
981
956
  if (queryID) {
982
- this._queryIdClientMap.delete(queryID)
957
+ this._queryIdClientMap.delete(queryID);
983
958
  }
984
- this._watchIdClientMap.delete(client.watchId)
985
- this._virtualWSClient.delete(client)
959
+ this._watchIdClientMap.delete(client.watchId);
960
+ this._virtualWSClient.delete(client);
986
961
 
987
962
  if (!this._virtualWSClient.size) {
988
963
  // no more existing watch, we should release the websocket connection
989
- this.close(CLOSE_EVENT_CODE.NoRealtimeListeners)
964
+ this.close(CLOSE_EVENT_CODE.NoRealtimeListeners);
990
965
  }
991
- }
966
+ };
992
967
  }