Cancelable promises proposal

Andrea Giammarchi andrea.giammarchi at
Mon Aug 3 17:19:15 UTC 2015

not so different from what I've proposed already, except it looks ugly with
a `self` at the end, and it's based on runtime method attachment that could
happen at any time or mislead, or forget to invoke reject etc etc ... I
will try to stay away from this thread 'cause I've already talked as much
as I could about this topic but my proposal was this one:

var p = new Proomise((resolve, reject, fnIfAborted) => {
  let timer = setTimeout(resolve, 3000, 'All Good');

  // **only** if fnIfAborted is invoked here
  // the promise will be cancelable, otherwise it cannot
  // be cancelable later on, and it's not possible
  // to even invoke fnIfAborted later on or asynchronously
  // this is the best I could think  to make the contract as simple as
  fnIfAborted(function () {

Once established that the user that created the Promise is the only one
capable of deciding if that could be cancelable or not, there's no way
anything else could interfeer with that cancelability, and the promise can
 be passed around as cancelable, or simply wrapped through another non
cancelable promise.

This gives the promise creator the ability to cancel it without exposing
such ability to the outer world.

The eventual `p.abort()` if executed after the promise has been
resolved/rejected will **not** invoke the `fnIfAborted` internally passed

Reasons such callback must be defined in the Promise scope is because only
there there would be eventually the ability to resolve, reject, or abort
the operation.

It's simple, it's probably a bit ugly, but it's there to solve edge cases (
basically all network related cases or every case that might take long time
and the user, or even  the developer, might get border and would like to do
something else instead of wasting resources )

Best Regards

On Mon, Aug 3, 2015 at 7:08 AM, Yad Smood <y.s.inside at> wrote:

> I have thought about something similar before, and used it in one of my
> libs. Recently, I have come up another idea, it was already implemented on
> Yaku:
> let Promise = require('yaku')
> // The `self` is the instance of the newly created promise.let p = new Promise((resolve, reject, self) => {
>     let tmr = setTimeout(resolve, 3000)
>     let self.abort = () => {
>         clearTimeout(tmr)
>         reject(new Error('abort promise'))
>     }
> })
> p.abort()
> The origin post is here:
> what do you think about it?
> 2015年8月3日(月) 8:43 Glen Huang <curvedmark at>:
>> I was discussing with Jake Archibald about cancelable promises the other
>> day. I was trying to convince him promise.cancel() might not be a good
>> idea. But that conversation unfortunately leans more towards on how the
>> abort API should be exposed on fetch. I did provide some thoughts on that
>> topic, and think the abort API represents a strong use case for cancelable
>> promises. But I feel what's more important is the underlying control flow
>> design.
>> So I would like to offer my proposal of cancelable promises here, and
>> would like to ask if you think it's a good idea, or if promise.cancel() is
>> actually a good idea and my understanding of promises is flawed.
>> I think that promises should be an observation API. In other words, it
>> should be kept as one-way communication. This keeps promises simple and
>> easy to reason about.
>> When we talk about cancelable promises, what we really want is the
>> ability to:
>> 1. abort the action that the root promise observes.
>> 2. let child promises show disinterest on the result of that action
>> With the premise that promises should be one-way communication, it's
>> clear that #1 should be achieved with a separate API. For example:
>> ```
>> let query = queryDB(sql);
>> query.done.then(data => console.log(data));
>> query.abort();
>> ```
>> This means you need to have access to that separate API in order to abort
>> the action, instead of just the promise.
>> And abort() rejects the root promise with a special error object, if it's
>> pending.
>> This also means the abort API doesn't have to be universal. Each action
>> initiator can design their own APIs to abort that action.
>> And correspondingly, to create a "cancelable promise" with the Promise
>> constructor, it can be as simple as:
>> ```
>> function doAction() {
>>         let abort;
>>         let done = new Promise((res, rej) => {
>>                 asyncAction(res, rej);
>>                 abort = () => rej(new AbortError());
>>         });
>>         return {done, abort};
>> }
>> ```
>> For #2, I propose we add a method to Promise.prototype that undos .then()
>> (probably also a sugar to undo .catch()) like removeEventListener undos
>> addEventListener. For example.
>> ```
>> let query = queryDB(sql);
>> let updateView = data => render(data);
>> let log = data => console.log(data);
>> query.done.then(updateView).then(log);
>> query.done.ignore(updateView); // deregister callback, updateView and log
>> will never be called
>> setTimeout(() => {
>>         query.done.then(updateView); // unless callback is registered
>> again
>> }, timeEnoughForQueryToFinish);
>> ```
>> You can think it as that each promise keeps a list of its child promises,
>> when the same callback is passed to .ignore() it sets a flag on the
>> corresponding child promise so that when itself resolves/rejects, it won't
>> pass that state to that child promise, unless that the same callback is
>> later registered again.
>> What do you think of this design? Do you think it covers all of your use
>> cases for cancelable promises?
>> I have to give credit for Kyle Simpson and Jake Archibald for this idea.
>> Kyle's opposition of sending signal back to the promise vendor, and Jake's
>> argument that we need a way to let an observer signal disinterest greatly
>> clarifies my understanding of promises.
>> I guess someone has probably expressed this idea somewhere in some way
>> (or in some libraries). Sorry if I missed that.
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at
> _______________________________________________
> es-discuss mailing list
> es-discuss at
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the es-discuss mailing list