DEV Community

Discussion on: Would it make sense to have "Symbol.promise" as standard JavaScript Symbol?

 
noseratio profile image
Andrew Nosenko • Edited

If your close is my cancel and cancelling an already settled Promise makes no harm:

I like your ideas, but the thing is, in the lacks of the standard cancellation framework for JavaScript, we all use different libraries. So, what works for you might not work for me :)

The prior art behind the current TC39 cancellation proposal is the .NET cancellation model, and it's also what's behind Prex, the library I use. It has two separate but connected concepts: CancellationTokenSource (the producer side of the API) and CancellationToken (the consumer part of it). Cancellation can be initiated on the source only, and observed on the token.

That makes sense, because cancellation is external to an API. But this way, using cancellation for stopping subscriptions gets a bit bulky, because I now need to create a temporary, linked token source just for the scope of my subscription, only to be able to cancel it (here is the complete runkit):

async function testSubscription(token) {
    const tokenSource = new prex.CancellationTokenSource([token]);
    const s = createSubscription(tokenSource.token);
    const p = prex.delay(prex.CancellationToken.none, 500); 
    try {
        await Promise.race([s, p]);
    } 
    finally {
        tokenSource.cancel();
        tokenSource.close();
    }
}
Enter fullscreen mode Exit fullscreen mode

Personally, I'd rather stick to using the subscription.close pattern, which is less verbose and reduces the number of allocations:

async function testSubscription(token) {
    const s = createSubscription(token);
    const p = prex.delay(prex.CancellationToken.none, 500); 
    try {
        await Promise.race([s.promise, p]);
    } 
    finally {
        s.close();
    }
}
Enter fullscreen mode Exit fullscreen mode

If there was standard Symbol.promise, it'd be Promise.race([s[Symbol.promise], p]), which I still think isn't too bad.

Your mileage with this may vary, depending on the libraries you use.

I also could give you another idea for fun [class AsyncOp]:

Prex has Deferred class for that, and I use it a lot :) It's semantically close to .NET TaskCompletionSource.

Thanks for the discussion!