Skip to content

Instantly share code, notes, and snippets.

@jaredcnance
Created March 7, 2018 03:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jaredcnance/6f0d5fa3d4a92910c96270cdf177f391 to your computer and use it in GitHub Desktop.
Save jaredcnance/6f0d5fa3d4a92910c96270cdf177f391 to your computer and use it in GitHub Desktop.
import CancellablePromise from '../CancellablePromise';
import Sleep from '../../../test/tools/Sleep';
describe('CancellablePromise', () => {
it('can be awaited', async () => {
let completed = false;
let basePromise = new Promise(resolve => {
setTimeout(resolve, 200);
}).then(() => (completed = true));
let cancellablePromise = new CancellablePromise(basePromise);
await cancellablePromise;
expect(completed).toEqual(true);
});
it('does not block if it is not awaited', async () => {
let completed = false;
let basePromise = new Promise(resolve => {
setTimeout(resolve, 200);
}).then(() => (completed = true));
let cancellablePromise = new CancellablePromise(basePromise);
cancellablePromise;
expect(completed).toEqual(false);
});
it('can be cancelled', async () => {
let completed = false;
let basePromise = new Promise(resolve => {
setTimeout(resolve, 200);
});
let cancellablePromise = new CancellablePromise(basePromise);
cancellablePromise.then(() => (completed = true));
cancellablePromise.cancel();
await Sleep(200);
expect(completed).toEqual(false);
});
});
export default class CancellablePromise<T> {
private resolver: (value?: T | PromiseLike<T>) => void;
private rejecter: (reason?: any) => void;
private readonly promise: Promise<T>;
private hasCanceled = false;
/**
* Creates an instance of CancellablePromise.
*
* @param {Promise<T>} innerPromise the underlying promise to be cancelled
*
* @memberOf CancellablePromise
*/
constructor(innerPromise: Promise<T>) {
this.promise = new Promise((resolve, reject) => {
this.resolver = resolve;
this.rejecter = reject;
});
innerPromise.then(
val =>
this.hasCanceled
? this.reject({ isCanceled: true })
: this.resolve(val),
error =>
this.hasCanceled
? this.reject({ isCanceled: true })
: this.reject(error),
);
}
then(
onfulfilled?: (value: T) => T | PromiseLike<T>,
onrejected?: (reason: any) => PromiseLike<never>,
): Promise<T> {
return this.promise.then(onfulfilled, onrejected);
}
catch(onRejected?: (reason: any) => PromiseLike<never>): Promise<T> {
return this.promise.catch(onRejected);
}
private resolve(value?: T | PromiseLike<T>): void {
return this.resolver(value);
}
private reject(reason?: any): void {
return this.rejecter(reason);
}
cancel() {
this.hasCanceled = true;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment