From 57528cbd2d65d1675b130ad50b712d080a3f24f8 Mon Sep 17 00:00:00 2001 From: Tajudeen Oyindamola Tajudeen <46614028+Pterjudin@users.noreply.github.com> Date: Sat, 18 Jan 2025 22:28:25 +0000 Subject: [PATCH] Update CancelablePromise.ts --- frontend/src/client/core/CancelablePromise.ts | 138 +++++++++--------- 1 file changed, 67 insertions(+), 71 deletions(-) diff --git a/frontend/src/client/core/CancelablePromise.ts b/frontend/src/client/core/CancelablePromise.ts index f47db79eae..d9bba59a0f 100644 --- a/frontend/src/client/core/CancelablePromise.ts +++ b/frontend/src/client/core/CancelablePromise.ts @@ -1,30 +1,30 @@ export class CancelError extends Error { constructor(message: string) { - super(message) - this.name = "CancelError" + super(message); + this.name = "CancelError"; } public get isCancelled(): boolean { - return true + return true; } } export interface OnCancel { - readonly isResolved: boolean - readonly isRejected: boolean - readonly isCancelled: boolean + readonly isResolved: boolean; + readonly isRejected: boolean; + readonly isCancelled: boolean; - (cancelHandler: () => void): void + (cancelHandler: () => void): void; } export class CancelablePromise implements Promise { - private _isResolved: boolean - private _isRejected: boolean - private _isCancelled: boolean - readonly cancelHandlers: (() => void)[] - readonly promise: Promise - private _resolve?: (value: T | PromiseLike) => void - private _reject?: (reason?: unknown) => void + private _isResolved: boolean = false; + private _isRejected: boolean = false; + private _isCancelled: boolean = false; + private readonly cancelHandlers: (() => void)[] = []; + private readonly promise: Promise; + private _resolve?: (value: T | PromiseLike) => void; + private _reject?: (reason?: unknown) => void; constructor( executor: ( @@ -33,94 +33,90 @@ export class CancelablePromise implements Promise { onCancel: OnCancel, ) => void, ) { - this._isResolved = false - this._isRejected = false - this._isCancelled = false - this.cancelHandlers = [] this.promise = new Promise((resolve, reject) => { - this._resolve = resolve - this._reject = reject - - const onResolve = (value: T | PromiseLike): void => { - if (this._isResolved || this._isRejected || this._isCancelled) { - return - } - this._isResolved = true - if (this._resolve) this._resolve(value) - } + this._resolve = resolve; + this._reject = reject; - const onReject = (reason?: unknown): void => { - if (this._isResolved || this._isRejected || this._isCancelled) { - return - } - this._isRejected = true - if (this._reject) this._reject(reason) - } + const onCancel = this.createOnCancel(); - const onCancel = (cancelHandler: () => void): void => { - if (this._isResolved || this._isRejected || this._isCancelled) { - return - } - this.cancelHandlers.push(cancelHandler) - } + executor(this.createResolve(), this.createReject(), onCancel); + }); + } + + private createResolve(): (value: T | PromiseLike) => void { + return (value: T | PromiseLike): void => { + if (this.isFinalState()) return; + this._isResolved = true; + this._resolve?.(value); + }; + } - Object.defineProperty(onCancel, "isResolved", { - get: (): boolean => this._isResolved, - }) + private createReject(): (reason?: unknown) => void { + return (reason?: unknown): void => { + if (this.isFinalState()) return; + this._isRejected = true; + this._reject?.(reason); + }; + } + + private createOnCancel(): OnCancel { + const onCancel = ((cancelHandler: () => void): void => { + if (this.isFinalState()) return; + this.cancelHandlers.push(cancelHandler); + }) as OnCancel; - Object.defineProperty(onCancel, "isRejected", { - get: (): boolean => this._isRejected, - }) + Object.defineProperties(onCancel, { + isResolved: { get: () => this._isResolved }, + isRejected: { get: () => this._isRejected }, + isCancelled: { get: () => this._isCancelled }, + }); - Object.defineProperty(onCancel, "isCancelled", { - get: (): boolean => this._isCancelled, - }) + return onCancel; + } - return executor(onResolve, onReject, onCancel as OnCancel) - }) + private isFinalState(): boolean { + return this._isResolved || this._isRejected || this._isCancelled; } get [Symbol.toStringTag]() { - return "Cancellable Promise" + return "Cancellable Promise"; } public then( onFulfilled?: ((value: T) => TResult1 | PromiseLike) | null, onRejected?: ((reason: unknown) => TResult2 | PromiseLike) | null, ): Promise { - return this.promise.then(onFulfilled, onRejected) + return this.promise.then(onFulfilled, onRejected); } public catch( onRejected?: ((reason: unknown) => TResult | PromiseLike) | null, ): Promise { - return this.promise.catch(onRejected) + return this.promise.catch(onRejected); } public finally(onFinally?: (() => void) | null): Promise { - return this.promise.finally(onFinally) + return this.promise.finally(onFinally); } public cancel(): void { - if (this._isResolved || this._isRejected || this._isCancelled) { - return - } - this._isCancelled = true - if (this.cancelHandlers.length) { - try { - for (const cancelHandler of this.cancelHandlers) { - cancelHandler() - } - } catch (error) { - console.warn("Cancellation threw an error", error) - return + if (this.isFinalState()) return; + + this._isCancelled = true; + + try { + for (const cancelHandler of this.cancelHandlers) { + cancelHandler(); } + } catch (error) { + console.error("Error during cancellation:", error); + } finally { + this.cancelHandlers.length = 0; + this._reject?.(new CancelError("Request aborted")); } - this.cancelHandlers.length = 0 - if (this._reject) this._reject(new CancelError("Request aborted")) } public get isCancelled(): boolean { - return this._isCancelled + return this._isCancelled; } }