CancellablePromise

node v14.14.0
version: 0.1.5
endpointsharetweet
Coming from C# and not having a standard cancellation framework in JavaScript is sad. Until TC39's ECMAScript Cancellation is implemented, I'm using my own CancellablePromise, based on Prex library.
// https://codereview.stackexchange.com/q/207116/35474 const prex = require('prex'); /** * 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 prex.CancellationTokenSource([token]); try { const linkedToken = linkedSource.token; linkedToken.throwIfCancellationRequested(); const deferred = new prex.Deferred(); linkedToken.register(() => deferred.reject(new prex.CancelError())); executor({ resolve: value => deferred.resolve(value), reject: error => deferred.reject(error), cancel: () => linkedSource.cancel(), token: linkedToken, }); return await deferred.promise; } finally { // this will free the linkedToken registration linkedSource.close(); } }; super((resolve, reject) => withCancellation().then(resolve, reject)); } } // // An example of using CancellablePromise // // async delay with cancellation function delayWithCancellation(timeoutMs, token) { console.log(`delayWithCancellation: ${timeoutMs}`); return new CancellablePromise(d => { token.throwIfCancellationRequested(); const id = setTimeout(d.resolve, timeoutMs); d.token.register(() => clearTimeout(id)); }, token); } // main async function main() { const tokenSource = new prex.CancellationTokenSource(); setTimeout(() => tokenSource.cancel(), 2000); // cancel after 2000ms const token = tokenSource.token; await delayWithCancellation(1000, token); console.log("successfully delayed."); // we should reach here await delayWithCancellation(3000, token); console.log("successfully delayed."); // we should not reach here } main().catch(error => console.log(`Error caught, ${error}`));
Loading…

no comments

    sign in to comment