Alternative way to achieve cancelable promise

Bergi a.d.bergi at web.de
Wed Oct 19 18:40:31 UTC 2016


Kagami Rosylight wrote:
> I want to find a way to replace cancellation token in the current [stage 1 cancelable promise proposal](https://github.com/tc39/proposal-cancelable-promises) with an alternative way which does not require passing an additional parameter.

You're not the only one who is unsatisfied with the current proposal :-)
Also have a look at
* https://github.com/stefanpenner/random/tree/master/cancellation
* https://github.com/rtm/cancelable-promise
* https://github.com/bergus/promise-cancellation (mine)

> Here is a short representation of [my current thought](https://github.com/SaschaNaz/cancelable):
>
> ```ts
> // A cancelable object supports new `Symbol.cancel`.
> // `object[Symbol.cancel]()` will cancel any tasks related to the object.
> interface Cancelable {
>   [@@cancel](): void;
> }
>
> interface Promise extends Cancelable {}
> ```

That's not going to happen. Promises are result values that can be 
passed to multiple consumers, and not every consumer should be allowed 
to cancel the computation. So by default, promises must not be cancellable.
There could be such promises that can be cancelled by whomever gets a 
hold on them - they are known as `Task`s iirc - but that needs to be an 
opt-in.

> // Here, a new `chain` object from promise constructor callback will
> // help chaining cancelable tasks and provide cancellation related
> // helper functions.

I don't see the major difference between these "chain" objects and 
"tokens" from the other proposals. Can you expand on that, please?

> function foo() {
>   return new Promise(async (resolve, reject, chain) => {
>     await nonCancelableSubWork1();
>     chain.throwIfCanceled(); // This line will throw `Cancel` object if the promise got a cancellation request
>     await nonCancelableSubWork2();
>     resolve();
>  });
> }

That's not going to work. You should never pass an `async function` to 
the `new Promise` constructor, have a look 
[here](http://stackoverflow.com/a/39409757/1048572).
Fortunately, the code in your actual proposal seems more reasonable here.

> And with some syntax sugar for readability:
>
> ```js
> cancelable function foo() {
>   // `chain` is a keyword inside cancelable function blocks
>   await nonCancelableSubWork1();
>   chain.throwIfCanceled(); // similar form like `new.target`
>   await nonCancelableSubWork2();
> }
>
> cancelable function bar() {
>   chain foo();
>   chain baz();
> }
>
> const promise = bar();
> promise.cancel();
> ```

If I understood correctly, your `chain` keyword could be used like 
`await`? What is the difference between them?

But I really like the idea of `cancelable function` sugar that does the 
housekeeping implicitly and returns cancellable promises automatically.
This very much reminds me of my own ideas 
https://github.com/bergus/promise-cancellation/blob/master/enhancements.md 
:-)

kind regards,
  Bergi


More information about the es-discuss mailing list