-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathAsyncWorkTracker.ts
More file actions
88 lines (77 loc) · 2.21 KB
/
AsyncWorkTracker.ts
File metadata and controls
88 lines (77 loc) · 2.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import { isPromise } from '../jsutils/isPromise.js';
import type { PromiseOrValue } from '../jsutils/PromiseOrValue.js';
/** @internal */
export class AsyncWorkTracker {
pendingAsyncWork: Set<Promise<void>>;
constructor() {
this.pendingAsyncWork = new Set<Promise<void>>();
}
add(promise: Promise<unknown>): void {
const pendingAsyncWork = this.pendingAsyncWork;
const promiseToSettle = promise.then(
() => {
pendingAsyncWork.delete(promiseToSettle);
},
() => {
pendingAsyncWork.delete(promiseToSettle);
},
);
pendingAsyncWork.add(promiseToSettle);
}
addValues(values: ReadonlyArray<PromiseOrValue<unknown>>): void {
for (const value of values) {
if (isPromise(value)) {
this.add(value);
}
}
}
async wait(): Promise<void> {
await Promise.resolve();
return waitForPendingSet(this.pendingAsyncWork);
}
promiseAllTrackOnReject<T>(
values: ReadonlyArray<PromiseOrValue<T>>,
): Promise<Array<T>> {
const promise = Promise.all(values);
promise.then(undefined, () => {
this.addValues(values);
});
return promise;
}
promiseTrackPending<T, TResult>(
values: ReadonlyArray<PromiseOrValue<T>>,
combinator: (promises: ReadonlyArray<Promise<T>>) => Promise<TResult>,
): Promise<TResult> {
const promises = values.map((value) => Promise.resolve(value));
const settled = promises.map(() => false);
for (let index = 0; index < promises.length; index++) {
const promise = promises[index];
promise.then(
() => {
settled[index] = true;
},
() => {
settled[index] = true;
},
);
}
const trackPending = () => {
for (let index = 0; index < promises.length; index++) {
if (!settled[index]) {
this.add(promises[index]);
}
}
};
const promise = combinator(promises);
promise.then(trackPending, trackPending);
return promise;
}
}
async function waitForPendingSet(
pendingPromises: ReadonlySet<Promise<void>>,
): Promise<void> {
while (pendingPromises.size > 0) {
// eslint-disable-next-line no-await-in-loop
await Promise.allSettled(Array.from(pendingPromises));
}
}