aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/frontend/src/utils/PendingTask.ts
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/frontend/src/utils/PendingTask.ts')
-rw-r--r--subprojects/frontend/src/utils/PendingTask.ts60
1 files changed, 60 insertions, 0 deletions
diff --git a/subprojects/frontend/src/utils/PendingTask.ts b/subprojects/frontend/src/utils/PendingTask.ts
new file mode 100644
index 00000000..51b79fb0
--- /dev/null
+++ b/subprojects/frontend/src/utils/PendingTask.ts
@@ -0,0 +1,60 @@
1import { getLogger } from './logger';
2
3const log = getLogger('utils.PendingTask');
4
5export class PendingTask<T> {
6 private readonly resolveCallback: (value: T) => void;
7
8 private readonly rejectCallback: (reason?: unknown) => void;
9
10 private resolved = false;
11
12 private timeout: number | null;
13
14 constructor(
15 resolveCallback: (value: T) => void,
16 rejectCallback: (reason?: unknown) => void,
17 timeoutMs?: number,
18 timeoutCallback?: () => void,
19 ) {
20 this.resolveCallback = resolveCallback;
21 this.rejectCallback = rejectCallback;
22 if (timeoutMs) {
23 this.timeout = setTimeout(() => {
24 if (!this.resolved) {
25 this.reject(new Error('Request timed out'));
26 if (timeoutCallback) {
27 timeoutCallback();
28 }
29 }
30 }, timeoutMs);
31 } else {
32 this.timeout = null;
33 }
34 }
35
36 resolve(value: T): void {
37 if (this.resolved) {
38 log.warn('Trying to resolve already resolved promise');
39 return;
40 }
41 this.markResolved();
42 this.resolveCallback(value);
43 }
44
45 reject(reason?: unknown): void {
46 if (this.resolved) {
47 log.warn('Trying to reject already resolved promise');
48 return;
49 }
50 this.markResolved();
51 this.rejectCallback(reason);
52 }
53
54 private markResolved() {
55 this.resolved = true;
56 if (this.timeout !== null) {
57 clearTimeout(this.timeout);
58 }
59 }
60}