Skip to content

Instantly share code, notes, and snippets.

@bolencki13
Last active November 15, 2023 02:04
Show Gist options
  • Save bolencki13/52a15694edbcbef0612a198095177463 to your computer and use it in GitHub Desktop.
Save bolencki13/52a15694edbcbef0612a198095177463 to your computer and use it in GitHub Desktop.
Use the abort controller to stop the promise chain from continuing if abort is called.
export type MaybeAbortablePromise<T> = AbortablePromise<T> | Promise<T>;
export class AbortablePromise<T> implements PromiseLike<T> {
readonly promise: Promise<T>;
readonly abortController: AbortController;
static resolve<T>(value: T, abortController?: AbortController): AbortablePromise<T>;
static resolve(abortController?: AbortController): AbortablePromise<void>;
static resolve<T>(value: T | undefined, abortController: AbortController = new AbortController()) {
return new AbortablePromise(Promise.resolve(value), abortController)
}
static reject<T = never>(reason?: any, abortController?: AbortController): AbortablePromise<T>;
static reject<T = never>(reason?: any, abortController: AbortController = new AbortController()) {
return AbortablePromise.resolve(abortController)
.then<T>(() => {
throw reason;
})
}
constructor(promise: Promise<T>, abortController: AbortController) {
this.promise = new Promise((res, rej) => {
promise.then((v) => {
if (!abortController.signal.aborted) {
return res(v);
}
}, rej)
});
this.abortController = abortController;
}
// Helper to abort the promise
abort(reason?: any) {
this.abortController.abort(reason);
}
then<TResult1 = T, TResult2 = never>(onfulfilled?: ((this: AbortablePromise<T>, value: T) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null | undefined): AbortablePromise<TResult1 | TResult2> {
const result = this.promise.then(onfulfilled?.bind(this), onrejected?.bind(this))
return new AbortablePromise(result, this.abortController);
}
catch<TResult = never>(onrejected?: ((this: AbortablePromise<T>, reason: any) => TResult | PromiseLike<TResult>) | null | undefined): AbortablePromise<T | TResult> {
const result = this.promise.catch(onrejected?.bind(this))
return new AbortablePromise(result, this.abortController)
}
finally(onfinally?: ((this: AbortablePromise<T>) => void) | undefined | null): AbortablePromise<T> {
const result = this.promise.finally(onfinally?.bind(this));
return new AbortablePromise(result, this.abortController);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment