**Updated**, I now use a much simplified version of `CancellablePromise`, I'll plan to publish it as an independent NPM package soon: /** * Class representing a cancellable promise. * @extends Promise */ class CancellablePromise extends Promise { static get [Symbol.species]() { return Promise; } /** * Create an instance of CancellablePromise promise. * @param {Function} executor - accepts an object with callbacks * and a token: { resolve, reject, cancel, token } * @param {CancellationToken} token - a cancellation token. */ constructor(executor, token) { const withCancellation = async () => { const linkedSource = new CancellationTokenSource(token); try { const linkedToken = linkedSource.token; linkedToken.throwIfCancellationRequested(); const deferred = new Deferred(); linkedToken.register(() => deferred.cancel()); executor({ resolve: value => deferred.resolve(value), reject: error => deferred.reject(error), cancel: () => linkedSource.cancel(), token: linkedToken, }); return await deferred; } finally { // this will free the linkedToken registration linkedSource.close(); } }; super((resolve, reject) => withCancellation().then(resolve, reject)); } }