-
Notifications
You must be signed in to change notification settings - Fork 2
/
promises.ts
94 lines (81 loc) · 2.52 KB
/
promises.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
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
89
90
91
92
93
94
// A promise extension with more methods. #promise
export class zPromise<T> {
static resolve<T>(value: T | PromiseLike<T>): zPromise<T> {
return new zPromise<T>((resolve) => resolve(value))
}
static reject(reason?: any): zPromise<never> {
return new zPromise<never>((_, reject) => reject(reason))
}
static try<T>(fn: () => T | PromiseLike<T>): zPromise<T> {
return new zPromise<T>((resolve) => resolve(fn()))
}
#promise: Promise<T>
constructor(
executor: (
resolve: (value: T | PromiseLike<T>) => void,
reject: (reason?: any) => void,
) => void,
) {
this.#promise = new Promise<T>((resolve, reject) => {
executor(resolve, reject)
})
}
then<TResult1 = T, TResult2 = never>(
onfulfilled?:
| ((value: T) => TResult1 | PromiseLike<TResult1>)
| undefined
| null,
onrejected?:
| ((reason: any) => TResult2 | PromiseLike<TResult2>)
| undefined
| null,
): zPromise<TResult1 | TResult2> {
return zPromise.resolve(this.#promise.then(onfulfilled, onrejected))
}
catch<TResult = never>(
onrejected?:
| ((reason: any) => TResult | PromiseLike<TResult>)
| undefined
| null,
): zPromise<TResult | T> {
return this.then<T, TResult>(null, onrejected)
}
passthrough(
onfulfilled?: ((value: T) => void | PromiseLike<void>) | undefined | null,
onrejected?: ((reason: any) => void | PromiseLike<void>) | undefined | null,
): zPromise<T> {
return this.then<T, never>(
(value) => {
if (typeof onfulfilled == "function")
return zPromise.resolve(onfulfilled(value)).then(() => value)
return value
},
(reason) => {
if (typeof onrejected == "function")
return zPromise.resolve(onrejected(reason)).then(() => {
throw reason
})
throw reason
},
)
}
finally(onfinally?: (() => void) | undefined | null) {
return this.passthrough(onfinally, onfinally)
}
spread<TResult1 = T, TResult2 = never>(
onfulfilled?:
| ((...args: T & any[]) => TResult1 | PromiseLike<TResult1>)
| undefined
| null,
onrejected?:
| ((reason: any) => TResult2 | PromiseLike<TResult2>)
| undefined
| null,
): zPromise<(T extends any[] ? TResult1 : T) | TResult2> {
return this.then<T extends any[] ? TResult1 : T, TResult2>((value) => {
if (typeof onfulfilled == "function" && Array.isArray(value))
return onfulfilled(...(value as any))
return value as any
}, onrejected)
}
}