UNPKG

3.89 kBJavaScriptView Raw
1async function delayUntil(delay = 0) {
2 return new Promise((yay) => {
3 const delayNum = 'number' === typeof (delay) ? +delay : 0;
4 if (delayNum < 1)
5 yay();
6 else
7 setTimeout(yay, delay);
8 });
9}
10
11async function globalPerformance() {
12 return ('undefined' !== typeof (window) ? window : global).performance;
13}
14
15class PollingMeasure {
16 constructor(name, duration, startTime) {
17 this.name = name;
18 this.duration = duration;
19 this.startTime = startTime;
20 this.entryType = 'polling-measure';
21 }
22 toJSON() {
23 return {
24 duration: this.duration,
25 entryType: this.entryType,
26 name: this.name,
27 startTime: this.startTime,
28 };
29 }
30}
31
32function isPromise(r) {
33 return 'function' === typeof (r.then);
34}
35class PollingObserver {
36 constructor(conditionCallback) {
37 this.conditionCallback = conditionCallback;
38 this._forceStop = false;
39 this._records = [];
40 this._isPolling = false;
41 if ('function' !== typeof (conditionCallback)) {
42 throw new TypeError(`'conditionCallback' is not defined`);
43 }
44 }
45 disconnect() {
46 this._forceStop = true;
47 if (!this._isPolling)
48 this._records = [];
49 }
50 async observe(callback, options) {
51 this._forceStop = false;
52 const { interval, timeout } = options || {};
53 const isValidInterval = 'number' === typeof (interval) && interval > 0;
54 const obsTimeout = 'number' === typeof (timeout) ? +timeout : -1;
55 const obsInterval = isValidInterval ? +interval : -1;
56 const perf = await globalPerformance();
57 const isInfinitePolling = obsTimeout < 1;
58 const records = this._records;
59 const onfinishCallback = this.onfinish;
60 const conditionCallback = this.conditionCallback;
61 let totalTime = 0;
62 let value = void 0;
63 let i = 0;
64 let status = 'finish';
65 let result = {};
66 try {
67 polling: while (true) {
68 if (this._forceStop)
69 break polling;
70 this._isPolling = true;
71 const conditionResult = conditionCallback(value, records, this);
72 const didConditionMeet = isPromise(conditionResult) ?
73 await conditionResult : conditionResult;
74 const didTimeout = isInfinitePolling ? false : totalTime >= obsTimeout;
75 if (didTimeout || didConditionMeet) {
76 status = didTimeout ? 'timeout' : status;
77 break polling;
78 }
79 const startAt = perf.now();
80 const r = callback();
81 value = isPromise(r) ? await r : r;
82 const endAt = perf.now();
83 const duration = endAt - startAt;
84 const timeLeft = isValidInterval ? obsInterval - duration : 0;
85 records.push(new PollingMeasure(`polling:${i}`, duration, startAt));
86 totalTime += (duration > obsInterval ? duration : obsInterval);
87 i += 1;
88 if (timeLeft > 0)
89 await delayUntil(timeLeft);
90 }
91 result = { status, value };
92 }
93 catch (e) {
94 result = { status: 'error', reason: e };
95 }
96 finally {
97 const recordsSlice = records.slice();
98 if (this._forceStop)
99 this._records = [];
100 this._isPolling = this._forceStop = false;
101 if ('function' === typeof (onfinishCallback)) {
102 onfinishCallback(result, recordsSlice, this);
103 }
104 }
105 }
106 takeRecords() {
107 return this._records;
108 }
109}
110
111export default PollingObserver;
112export { PollingObserver };
113//# sourceMappingURL=polling-observer.js.map