/
promise.ts
52 lines (41 loc) · 1.41 KB
/
promise.ts
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
/**
* Wraps a Promise and lets you observe its state.
*/
export class StatefulPromise<T> implements Promise<T>{
#state: PromiseState = "pending"
#inner: Promise<T>
constructor(p: Promise<T>) {
this.#inner = p
this.#watch(p)
}
get state(): PromiseState { return this.#state }
async #watch(p: Promise<T>) {
try {
await p
this.#state = "resolved"
} catch (_err) {
this.#state = "rejected"
}
}
// Wrappers. (Thanks, VSCode, for generating these types. :p)
then<TResult1=T,TResult2=never>(
onfulfilled?: ((value: T) => TResult1|PromiseLike<TResult1>)|null|undefined,
onrejected?: ((reason: unknown) => TResult2|PromiseLike<TResult2>)|null|undefined
): Promise<TResult1|TResult2> {
return this.#inner.then(onfulfilled, onrejected)
}
catch<TResult=never>(
onrejected?: ((reason: unknown) => TResult|PromiseLike<TResult>)|null|undefined
): Promise<T|TResult> {
return this.#inner.catch(onrejected)
}
finally(onfinally?: (() => void)|null|undefined): Promise<T> {
return this.#inner.finally(onfinally)
}
[Symbol.toStringTag] = "StatefulPromise"
}
export type PromiseState = "pending" | "resolved" | "rejected"
/** Shorter helper method */
export function stateful<T>(p: Promise<T>): StatefulPromise<T> {
return new StatefulPromise(p)
}