11export class CancelError extends Error {
22 constructor ( message : string ) {
3- super ( message )
4- this . name = "CancelError"
3+ super ( message ) ;
4+ this . name = "CancelError" ;
55 }
66
77 public get isCancelled ( ) : boolean {
8- return true
8+ return true ;
99 }
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
21+ private _isResolved : boolean = false ;
22+ private _isRejected : boolean = false ;
23+ private _isCancelled : boolean = false ;
24+ private readonly cancelHandlers : ( ( ) => void ) [ ] = [ ] ;
25+ private readonly promise : Promise < T > ;
26+ private _resolve ?: ( value : T | PromiseLike < T > ) => void ;
27+ private _reject ?: ( reason ?: unknown ) => void ;
2828
2929 constructor (
3030 executor : (
@@ -33,94 +33,90 @@ export class CancelablePromise<T> implements Promise<T> {
3333 onCancel : OnCancel ,
3434 ) => void ,
3535 ) {
36- this . _isResolved = false
37- this . _isRejected = false
38- this . _isCancelled = false
39- this . cancelHandlers = [ ]
4036 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- }
37+ this . _resolve = resolve ;
38+ this . _reject = reject ;
5139
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- }
40+ const onCancel = this . createOnCancel ( ) ;
5941
60- const onCancel = ( cancelHandler : ( ) => void ) : void => {
61- if ( this . _isResolved || this . _isRejected || this . _isCancelled ) {
62- return
63- }
64- this . cancelHandlers . push ( cancelHandler )
65- }
42+ executor ( this . createResolve ( ) , this . createReject ( ) , onCancel ) ;
43+ } ) ;
44+ }
45+
46+ private createResolve ( ) : ( value : T | PromiseLike < T > ) => void {
47+ return ( value : T | PromiseLike < T > ) : void => {
48+ if ( this . isFinalState ( ) ) return ;
49+ this . _isResolved = true ;
50+ this . _resolve ?.( value ) ;
51+ } ;
52+ }
6653
67- Object . defineProperty ( onCancel , "isResolved" , {
68- get : ( ) : boolean => this . _isResolved ,
69- } )
54+ private createReject ( ) : ( reason ?: unknown ) => void {
55+ return ( reason ?: unknown ) : void => {
56+ if ( this . isFinalState ( ) ) return ;
57+ this . _isRejected = true ;
58+ this . _reject ?.( reason ) ;
59+ } ;
60+ }
61+
62+ private createOnCancel ( ) : OnCancel {
63+ const onCancel = ( ( cancelHandler : ( ) => void ) : void => {
64+ if ( this . isFinalState ( ) ) return ;
65+ this . cancelHandlers . push ( cancelHandler ) ;
66+ } ) as OnCancel ;
7067
71- Object . defineProperty ( onCancel , "isRejected" , {
72- get : ( ) : boolean => this . _isRejected ,
73- } )
68+ Object . defineProperties ( onCancel , {
69+ isResolved : { get : ( ) => this . _isResolved } ,
70+ isRejected : { get : ( ) => this . _isRejected } ,
71+ isCancelled : { get : ( ) => this . _isCancelled } ,
72+ } ) ;
7473
75- Object . defineProperty ( onCancel , "isCancelled" , {
76- get : ( ) : boolean => this . _isCancelled ,
77- } )
74+ return onCancel ;
75+ }
7876
79- return executor ( onResolve , onReject , onCancel as OnCancel )
80- } )
77+ private isFinalState ( ) : boolean {
78+ return this . _isResolved || this . _isRejected || this . _isCancelled ;
8179 }
8280
8381 get [ Symbol . toStringTag ] ( ) {
84- return "Cancellable Promise"
82+ return "Cancellable Promise" ;
8583 }
8684
8785 public then < TResult1 = T , TResult2 = never > (
8886 onFulfilled ?: ( ( value : T ) => TResult1 | PromiseLike < TResult1 > ) | null ,
8987 onRejected ?: ( ( reason : unknown ) => TResult2 | PromiseLike < TResult2 > ) | null ,
9088 ) : Promise < TResult1 | TResult2 > {
91- return this . promise . then ( onFulfilled , onRejected )
89+ return this . promise . then ( onFulfilled , onRejected ) ;
9290 }
9391
9492 public catch < TResult = never > (
9593 onRejected ?: ( ( reason : unknown ) => TResult | PromiseLike < TResult > ) | null ,
9694 ) : Promise < T | TResult > {
97- return this . promise . catch ( onRejected )
95+ return this . promise . catch ( onRejected ) ;
9896 }
9997
10098 public finally ( onFinally ?: ( ( ) => void ) | null ) : Promise < T > {
101- return this . promise . finally ( onFinally )
99+ return this . promise . finally ( onFinally ) ;
102100 }
103101
104102 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
103+ if ( this . isFinalState ( ) ) return ;
104+
105+ this . _isCancelled = true ;
106+
107+ try {
108+ for ( const cancelHandler of this . cancelHandlers ) {
109+ cancelHandler ( ) ;
117110 }
111+ } catch ( error ) {
112+ console . error ( "Error during cancellation:" , error ) ;
113+ } finally {
114+ this . cancelHandlers . length = 0 ;
115+ this . _reject ?.( new CancelError ( "Request aborted" ) ) ;
118116 }
119- this . cancelHandlers . length = 0
120- if ( this . _reject ) this . _reject ( new CancelError ( "Request aborted" ) )
121117 }
122118
123119 public get isCancelled ( ) : boolean {
124- return this . _isCancelled
120+ return this . _isCancelled ;
125121 }
126122}
0 commit comments