@@ -66,16 +66,21 @@ type PromiseSettledResult<T> =
66
66
| PromiseFulfilledResult < T >
67
67
| PromiseRejectedResult ;
68
68
69
+ type QueueTask = {
70
+ fulfilled : ( ) => void ;
71
+ rejected : ( ) => void ;
72
+ } ;
73
+
69
74
export class MyPromise < T = any > implements IMyPromise < T > {
70
75
#state: ValueOf < typeof STATES > = STATES . PENDING ;
71
76
77
+ #completed = false ;
78
+
72
79
#value: T | PromiseLike < T > | undefined = undefined ;
73
80
74
81
#reason: any = undefined ;
75
82
76
- #fulfilledCallbacksQueue: ( ( ) => void ) [ ] = [ ] ;
77
-
78
- #rejectedCallbacksQueue: ( ( ) => void ) [ ] = [ ] ;
83
+ #callbacksQueue: QueueTask [ ] = [ ] ;
79
84
80
85
// --- Resolve --------------------
81
86
static resolve ( ) : MyPromise < void > ;
@@ -239,30 +244,24 @@ export class MyPromise<T = any> implements IMyPromise<T> {
239
244
240
245
// Resolve -----
241
246
const internalResolve = ( value : T | PromiseLike < T > ) => {
242
- if ( this . #state !== STATES . PENDING ) return ;
247
+ if ( this . #completed) return ;
248
+ this . #completed = true ;
243
249
244
250
this . #state = STATES . FULFILLED ;
245
251
this . #value = value ;
246
252
247
- this . #fulfilledCallbacksQueue. forEach ( ( callback ) => {
248
- callback ( ) ;
249
- } ) ;
250
-
251
- this . #fulfilledCallbacksQueue = [ ] ;
253
+ this . #executeCallbacksQueue( ) ;
252
254
} ;
253
255
254
256
// Reject -----
255
257
const internalReject = ( reason : any ) => {
256
- if ( this . #state !== STATES . PENDING ) return ;
258
+ if ( this . #completed) return ;
259
+ this . #completed = true ;
257
260
258
261
this . #state = STATES . REJECTED ;
259
262
this . #reason = reason ;
260
263
261
- this . #rejectedCallbacksQueue. forEach ( ( callback ) => {
262
- callback ( ) ;
263
- } ) ;
264
-
265
- this . #fulfilledCallbacksQueue = [ ] ;
264
+ this . #executeCallbacksQueue( ) ;
266
265
} ;
267
266
268
267
// Constructor execution -----
@@ -282,12 +281,9 @@ export class MyPromise<T = any> implements IMyPromise<T> {
282
281
) {
283
282
return new MyPromise ( ( resolve , reject ) => {
284
283
if ( this . #state === STATES . PENDING ) {
285
- this . #fulfilledCallbacksQueue. push ( ( ) => {
286
- handleFulfilled ( this . #value as T ) ;
287
- } ) ;
288
-
289
- this . #rejectedCallbacksQueue. push ( ( ) => {
290
- handleRejected ( this . #reason) ;
284
+ this . #callbacksQueue. push ( {
285
+ fulfilled : ( ) => handleFulfilled ( this . #value as T ) ,
286
+ rejected : ( ) => handleRejected ( this . #reason) ,
291
287
} ) ;
292
288
} else if ( this . #state === STATES . FULFILLED ) {
293
289
if ( isThenable ( this . #value) ) {
@@ -338,6 +334,25 @@ export class MyPromise<T = any> implements IMyPromise<T> {
338
334
} ) ;
339
335
}
340
336
337
+ #executeCallbacksQueue( ) {
338
+ let index = 0 ;
339
+ const chain = this . #callbacksQueue;
340
+
341
+ while ( index !== chain . length ) {
342
+ const { fulfilled, rejected } = chain [ index ] ;
343
+
344
+ if ( this . #state === STATES . FULFILLED ) {
345
+ fulfilled ( ) ;
346
+ } else {
347
+ rejected ( ) ;
348
+ }
349
+
350
+ index += 1 ;
351
+ }
352
+
353
+ this . #callbacksQueue = [ ] ;
354
+ }
355
+
341
356
// --- Catch --------------------
342
357
catch < TResult = never > (
343
358
onrejected ?: ( ( reason : any ) => TResult | PromiseLike < TResult > ) | null ,
0 commit comments