|
@@ -20,24 +20,56 @@ export interface Cancellable {
|
|
|
|
|
|
|
|
export class CancellablePromise<T> extends Promise<T> implements Cancellable {
|
|
export class CancellablePromise<T> extends Promise<T> implements Cancellable {
|
|
|
private readonly onCancel?: () => void;
|
|
private readonly onCancel?: () => void;
|
|
|
|
|
+ private readonly rejectHandler?: (reason?: unknown) => void;
|
|
|
|
|
+ private cancelPrevented?: boolean;
|
|
|
|
|
+ cancelled?: boolean;
|
|
|
|
|
|
|
|
constructor(
|
|
constructor(
|
|
|
handlers: (
|
|
handlers: (
|
|
|
resolve: (value?: T | PromiseLike<T>) => void,
|
|
resolve: (value?: T | PromiseLike<T>) => void,
|
|
|
reject: (reason?: unknown) => void,
|
|
reject: (reason?: unknown) => void,
|
|
|
- onCancel?: (cancelHandler: () => void) => void
|
|
|
|
|
|
|
+ onCancel: (cancelHandler: () => void) => void
|
|
|
) => void
|
|
) => void
|
|
|
) {
|
|
) {
|
|
|
let onCancel: undefined | (() => void) = undefined;
|
|
let onCancel: undefined | (() => void) = undefined;
|
|
|
- super((resolve, reject) =>
|
|
|
|
|
- handlers(resolve, reject, (cancelHandler: () => void) => (onCancel = cancelHandler))
|
|
|
|
|
- );
|
|
|
|
|
|
|
+ let rejectHandler: undefined | ((reason?: unknown) => void) = undefined;
|
|
|
|
|
+ super((resolve, reject) => {
|
|
|
|
|
+ rejectHandler = reject;
|
|
|
|
|
+ return handlers(resolve, reject, (cancelHandler: () => void) => (onCancel = cancelHandler));
|
|
|
|
|
+ });
|
|
|
|
|
+ this.rejectHandler = rejectHandler;
|
|
|
this.onCancel = onCancel;
|
|
this.onCancel = onCancel;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- cancel(): void {
|
|
|
|
|
- if (this.onCancel) {
|
|
|
|
|
- this.onCancel();
|
|
|
|
|
|
|
+ async cancel(): Promise<void> {
|
|
|
|
|
+ if (!this.cancelPrevented) {
|
|
|
|
|
+ const testSymbol = Symbol();
|
|
|
|
|
+ const firstToFinish = await Promise.race([this, Promise.resolve(testSymbol)]);
|
|
|
|
|
+ if (firstToFinish === testSymbol) {
|
|
|
|
|
+ if (this.onCancel) {
|
|
|
|
|
+ this.onCancel();
|
|
|
|
|
+ }
|
|
|
|
|
+ if (this.rejectHandler) {
|
|
|
|
|
+ this.rejectHandler();
|
|
|
|
|
+ }
|
|
|
|
|
+ this.cancelled = true;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ preventCancel(): void {
|
|
|
|
|
+ this.cancelPrevented = true;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ static reject<T = unknown>(reason?: unknown): CancellablePromise<T> {
|
|
|
|
|
+ return new CancellablePromise<T>((resolve, reject) => {
|
|
|
|
|
+ reject(reason);
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ static resolve<T = unknown>(value?: T | PromiseLike<T>): CancellablePromise<T> {
|
|
|
|
|
+ return new CancellablePromise<T>(resolve => {
|
|
|
|
|
+ resolve(value);
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|