CancellablePromise

node v14.20.1
version: 0.1.11
endpointsharetweet
Coming from C#, I need a cancellation framework in JavaScript. Until TC39's ECMAScript Cancellation is implemented, I'm using this CancellablePromise, based on Prex library.
// by @noseratio // https://gist.github.com/noseratio/141a2df292b108ec4c147db4530379d2 // https://runkit.com/noseratio/cancellablepromise const prex = require('prex'); /** * A cancellable promise. * @extends Promise */ class CancellablePromise extends Promise { static get [Symbol.species]() { // https://tinyurl.com/promise-constructor return Promise; } constructor(executor, token) { const withCancellation = async () => { // create a new linked token source const linkedSource = new prex.CancellationTokenSource(token? [token]: []); try { const linkedToken = linkedSource.token; const deferred = new prex.Deferred(); linkedToken.register(() => deferred.reject(new prex.CancelError())); executor({ resolve: value => deferred.resolve(value), reject: error => deferred.reject(error), token: linkedToken }); await deferred.promise; } finally { // this will also free all linkedToken registrations, // so the executor doesn't have to worry about it linkedSource.close(); } }; super((resolve, reject) => withCancellation().then(resolve, reject)); } } /** * A cancellable delay. * @extends Promise */ class Delay extends CancellablePromise { static get [Symbol.species]() { return Promise; } constructor(delayMs, token) { super(r => { const id = setTimeout(r.resolve, delayMs); r.token.register(() => clearTimeout(id)); }, token); } } // main async function main() { const tokenSource = new prex.CancellationTokenSource(); const token = tokenSource.token; setTimeout(() => tokenSource.cancel(), 2000); // cancel after 2000ms let delay = 1000; console.log(`delaying by ${delay}ms`); await new Delay(delay, token); console.log("successfully delayed."); // we should reach here delay = 2000; console.log(`delaying by ${delay}ms`); await new Delay(delay, token); console.log("successfully delayed."); // we should not reach here } main().catch(error => console.error(`Error caught, ${error}`));
Loading…

no comments

    sign in to comment