tc39 / proposal-cancelable-promises

Former home of the now-withdrawn cancelable promises proposal for JavaScript
Other
376 stars 29 forks source link

What's the deal with PromiseToReturn? #41

Closed bergus closed 8 years ago

bergus commented 8 years ago

I'm probably missing something, but what is this necessary for and how is it supposed to work in the standard examples?

async function weirdThing() {
    const { token, cancel } = CancelToken.source();
    await.cancelToken = token;
    await delay(1000, token); // this line does not make a difference
    cancel("oops");
    return "huh";
}
const p = weirdThing();
p.then(console.log, console.log);

If I am not mistaken, the execution context's PromiseToCancel and PromiseToReturn are both set to p, making the cancel() call reject the promise so that we are going to see Cancel(oops) in the console, ignoring the return value. Is that expected?

domenic commented 8 years ago

Right, that's the idea. I wasn't sure about this but the alternative seems worse, i.e. in your above example, despite having canceled the token which is tied to the function's lifetime, you get a fulfilled promise. What do you think?

bergus commented 8 years ago

Oh, I really like it, it just clashes a bit more with the "propagate cancellation downwards as a promise result" idea. We also need to consider the case

async function() {
    const { token, cancel } = CancelToken.source();
    await.cancelToken = token;
    cancel();
    try {
        await moreWorkA(…);
    } catch(e) {}
    await.cancelToken = null; // or a new CancelToken()
    await moreWorkB(…);
    return result;
}

Here moreWorkA is raced against an already cancelled token, which means it's disregared immediately, but moreWorkB is not dealt with so favourably. It might be highly unexpected for users… but it's just an edge case. Some ideas

You might want to read the source of my couroutine.cancel implementation (like await.cancelToken for generators) here and here for some inspiration or play around with it - while it does follow my own approach at cancellation in general, this stuff is very similar.

domenic commented 8 years ago

Very interesting. That edge-case is pretty troubling; in general the whole thing where we've already decided that the returned promise should be rejected, but we keep running code anyway, seems problematic, and your code highlights it.

I guess I see two approaches: