11export class CancelError extends Error {
2- constructor ( message : string ) {
3- super ( message )
4- this . name = " CancelError"
5- }
6-
7- public get isCancelled ( ) : boolean {
8- return true
9- }
2+ constructor ( message : string ) {
3+ super ( message ) ;
4+ this . name = ' CancelError' ;
5+ }
6+
7+ public get isCancelled ( ) : boolean {
8+ return true ;
9+ }
1010}
1111
1212export interface OnCancel {
13- readonly isResolved : boolean
14- readonly isRejected : boolean
15- readonly isCancelled : boolean
13+ readonly isResolved : boolean ;
14+ readonly isRejected : boolean ;
15+ readonly isCancelled : boolean ;
1616
17- ( cancelHandler : ( ) => void ) : void
17+ ( cancelHandler : ( ) => void ) : void ;
1818}
1919
2020export class CancelablePromise < T > implements Promise < T > {
21- private _isResolved : boolean
22- private _isRejected : boolean
23- private _isCancelled : boolean
24- readonly cancelHandlers : ( ( ) => void ) [ ]
25- readonly promise : Promise < T >
26- private _resolve ?: ( value : T | PromiseLike < T > ) => void
27- private _reject ?: ( reason ?: unknown ) => void
28-
29- constructor (
30- executor : (
31- resolve : ( value : T | PromiseLike < T > ) => void ,
32- reject : ( reason ?: unknown ) => void ,
33- onCancel : OnCancel ,
34- ) => void ,
35- ) {
36- this . _isResolved = false
37- this . _isRejected = false
38- this . _isCancelled = false
39- this . cancelHandlers = [ ]
40- this . promise = new Promise < T > ( ( resolve , reject ) => {
41- this . _resolve = resolve
42- this . _reject = reject
43-
44- const onResolve = ( value : T | PromiseLike < T > ) : void => {
45- if ( this . _isResolved || this . _isRejected || this . _isCancelled ) {
46- return
47- }
48- this . _isResolved = true
49- if ( this . _resolve ) this . _resolve ( value )
50- }
51-
52- const onReject = ( reason ?: unknown ) : void => {
53- if ( this . _isResolved || this . _isRejected || this . _isCancelled ) {
54- return
55- }
56- this . _isRejected = true
57- if ( this . _reject ) this . _reject ( reason )
58- }
59-
60- const onCancel = ( cancelHandler : ( ) => void ) : void => {
61- if ( this . _isResolved || this . _isRejected || this . _isCancelled ) {
62- return
63- }
64- this . cancelHandlers . push ( cancelHandler )
65- }
66-
67- Object . defineProperty ( onCancel , " isResolved" , {
68- get : ( ) : boolean => this . _isResolved ,
69- } )
70-
71- Object . defineProperty ( onCancel , " isRejected" , {
72- get : ( ) : boolean => this . _isRejected ,
73- } )
74-
75- Object . defineProperty ( onCancel , " isCancelled" , {
76- get : ( ) : boolean => this . _isCancelled ,
77- } )
78-
79- return executor ( onResolve , onReject , onCancel as OnCancel )
80- } )
81- }
82-
83- get [ Symbol . toStringTag ] ( ) {
84- return "Cancellable Promise"
85- }
86-
87- public then < TResult1 = T , TResult2 = never > (
88- onFulfilled ?: ( ( value : T ) => TResult1 | PromiseLike < TResult1 > ) | null ,
89- onRejected ?: ( ( reason : unknown ) => TResult2 | PromiseLike < TResult2 > ) | null ,
90- ) : Promise < TResult1 | TResult2 > {
91- return this . promise . then ( onFulfilled , onRejected )
92- }
93-
94- public catch < TResult = never > (
95- onRejected ?: ( ( reason : unknown ) => TResult | PromiseLike < TResult > ) | null ,
96- ) : Promise < T | TResult > {
97- return this . promise . catch ( onRejected )
98- }
99-
100- public finally ( onFinally ?: ( ( ) => void ) | null ) : Promise < T > {
101- return this . promise . finally ( onFinally )
102- }
103-
104- public cancel ( ) : void {
105- if ( this . _isResolved || this . _isRejected || this . _isCancelled ) {
106- return
107- }
108- this . _isCancelled = true
109- if ( this . cancelHandlers . length ) {
110- try {
111- for ( const cancelHandler of this . cancelHandlers ) {
112- cancelHandler ( )
113- }
114- } catch ( error ) {
115- console . warn ( " Cancellation threw an error" , error )
116- return
117- }
118- }
119- this . cancelHandlers . length = 0
120- if ( this . _reject ) this . _reject ( new CancelError ( " Request aborted" ) )
121- }
122-
123- public get isCancelled ( ) : boolean {
124- return this . _isCancelled
125- }
126- }
21+ private _isResolved : boolean ;
22+ private _isRejected : boolean ;
23+ private _isCancelled : boolean ;
24+ readonly cancelHandlers : ( ( ) => void ) [ ] ;
25+ readonly promise : Promise < T > ;
26+ private _resolve ?: ( value : T | PromiseLike < T > ) => void ;
27+ private _reject ?: ( reason ?: unknown ) => void ;
28+
29+ constructor (
30+ executor : (
31+ resolve : ( value : T | PromiseLike < T > ) => void ,
32+ reject : ( reason ?: unknown ) => void ,
33+ onCancel : OnCancel
34+ ) => void
35+ ) {
36+ this . _isResolved = false ;
37+ this . _isRejected = false ;
38+ this . _isCancelled = false ;
39+ this . cancelHandlers = [ ] ;
40+ this . promise = new Promise < T > ( ( resolve , reject ) => {
41+ this . _resolve = resolve ;
42+ this . _reject = reject ;
43+
44+ const onResolve = ( value : T | PromiseLike < T > ) : void => {
45+ if ( this . _isResolved || this . _isRejected || this . _isCancelled ) {
46+ return ;
47+ }
48+ this . _isResolved = true ;
49+ if ( this . _resolve ) this . _resolve ( value ) ;
50+ } ;
51+
52+ const onReject = ( reason ?: unknown ) : void => {
53+ if ( this . _isResolved || this . _isRejected || this . _isCancelled ) {
54+ return ;
55+ }
56+ this . _isRejected = true ;
57+ if ( this . _reject ) this . _reject ( reason ) ;
58+ } ;
59+
60+ const onCancel = ( cancelHandler : ( ) => void ) : void => {
61+ if ( this . _isResolved || this . _isRejected || this . _isCancelled ) {
62+ return ;
63+ }
64+ this . cancelHandlers . push ( cancelHandler ) ;
65+ } ;
66+
67+ Object . defineProperty ( onCancel , ' isResolved' , {
68+ get : ( ) : boolean => this . _isResolved ,
69+ } ) ;
70+
71+ Object . defineProperty ( onCancel , ' isRejected' , {
72+ get : ( ) : boolean => this . _isRejected ,
73+ } ) ;
74+
75+ Object . defineProperty ( onCancel , ' isCancelled' , {
76+ get : ( ) : boolean => this . _isCancelled ,
77+ } ) ;
78+
79+ return executor ( onResolve , onReject , onCancel as OnCancel ) ;
80+ } ) ;
81+ }
82+
83+ get [ Symbol . toStringTag ] ( ) {
84+ return "Cancellable Promise" ;
85+ }
86+
87+ public then < TResult1 = T , TResult2 = never > (
88+ onFulfilled ?: ( ( value : T ) => TResult1 | PromiseLike < TResult1 > ) | null ,
89+ onRejected ?: ( ( reason : unknown ) => TResult2 | PromiseLike < TResult2 > ) | null
90+ ) : Promise < TResult1 | TResult2 > {
91+ return this . promise . then ( onFulfilled , onRejected ) ;
92+ }
93+
94+ public catch < TResult = never > (
95+ onRejected ?: ( ( reason : unknown ) => TResult | PromiseLike < TResult > ) | null
96+ ) : Promise < T | TResult > {
97+ return this . promise . catch ( onRejected ) ;
98+ }
99+
100+ public finally ( onFinally ?: ( ( ) => void ) | null ) : Promise < T > {
101+ return this . promise . finally ( onFinally ) ;
102+ }
103+
104+ public cancel ( ) : void {
105+ if ( this . _isResolved || this . _isRejected || this . _isCancelled ) {
106+ return ;
107+ }
108+ this . _isCancelled = true ;
109+ if ( this . cancelHandlers . length ) {
110+ try {
111+ for ( const cancelHandler of this . cancelHandlers ) {
112+ cancelHandler ( ) ;
113+ }
114+ } catch ( error ) {
115+ console . warn ( ' Cancellation threw an error' , error ) ;
116+ return ;
117+ }
118+ }
119+ this . cancelHandlers . length = 0 ;
120+ if ( this . _reject ) this . _reject ( new CancelError ( ' Request aborted' ) ) ;
121+ }
122+
123+ public get isCancelled ( ) : boolean {
124+ return this . _isCancelled ;
125+ }
126+ }
0 commit comments