UNPKG

3.19 kBJavaScriptView Raw
1import { delayUntil } from '../delay-until/index';
2import { PollingMeasure } from './polling-measure';
3function isPromise(r) {
4 return 'function' === typeof (r.then);
5}
6const perf = globalThis.performance;
7export class PollingObserver {
8 conditionCallback;
9 onfinish;
10 _forceStop = false;
11 _records = [];
12 _isPolling = false;
13 constructor(conditionCallback) {
14 this.conditionCallback = conditionCallback;
15 if ('function' !== typeof (conditionCallback)) {
16 throw new TypeError(`'conditionCallback' is not defined`);
17 }
18 }
19 disconnect() {
20 this._forceStop = true;
21 if (!this._isPolling)
22 this._records = [];
23 }
24 async observe(callback, options) {
25 this._forceStop = false;
26 const { interval, timeout } = options || {};
27 const isValidInterval = 'number' === typeof (interval) && interval > 0;
28 const obsTimeout = 'number' === typeof (timeout) ? +timeout : -1;
29 const obsInterval = isValidInterval ? +interval : 100;
30 const isInfinitePolling = obsTimeout < 1;
31 const records = this._records;
32 const onfinishCallback = this.onfinish;
33 const conditionCallback = this.conditionCallback;
34 const loop = true;
35 let totalTime = 0;
36 let value = void 0;
37 let i = 0;
38 let status = 'finish';
39 let result = {};
40 try {
41 polling: while (loop) {
42 if (this._forceStop)
43 break polling;
44 this._isPolling = true;
45 const conditionResult = conditionCallback(value, records, this);
46 const didConditionMeet = isPromise(conditionResult) ?
47 await conditionResult : conditionResult;
48 const didTimeout = isInfinitePolling ? false : totalTime >= obsTimeout;
49 if (didTimeout || didConditionMeet) {
50 status = didTimeout ? 'timeout' : status;
51 break polling;
52 }
53 const startAt = perf.now();
54 const r = callback();
55 value = isPromise(r) ? await r : r;
56 const endAt = perf.now();
57 const duration = endAt - startAt;
58 const timeLeft = isValidInterval ? obsInterval - duration : 0;
59 records.push(new PollingMeasure(`polling:${i}`, duration, startAt));
60 totalTime += (duration > obsInterval ? duration : obsInterval);
61 i += 1;
62 if (timeLeft > 0)
63 await delayUntil(timeLeft);
64 }
65 result = { status, value };
66 }
67 catch (e) {
68 result = { status: 'error', reason: e };
69 }
70 finally {
71 const recordsSlice = records.slice();
72 if (this._forceStop)
73 this._records = [];
74 this._isPolling = this._forceStop = false;
75 if ('function' === typeof (onfinishCallback)) {
76 onfinishCallback(result, recordsSlice, this);
77 }
78 }
79 }
80 takeRecords() {
81 return this._records;
82 }
83}
84//# sourceMappingURL=polling-observer.js.map
\No newline at end of file