Cancelable promises proposal

Andrea Giammarchi andrea.giammarchi at gmail.com
Tue Aug 4 05:34:49 UTC 2015


> if used when cancelable is true

if used when cancelable is NOT true, so throw if non cancelable

On Tue, Aug 4, 2015 at 6:32 AM, Andrea Giammarchi <
andrea.giammarchi at gmail.com> wrote:

> my proposal doesn't make abortability accidental, only promises that has
> passed through their initialization the callback would be cancelable,and
> this could be reflected through a `.cancelable` property. We could have
>  `.abort()` throwing if used when cancelable is true ( or not
> undefined for backward compatiblity sake )
>
> The only problem I see with my proposal is thay purists would  never
> accept cancel-ability in first place, and pragmatists would never find out
> what should be the behavior once aborted 'cause Promise can only reject and
> never be ignored.
>
> So the TL;DR is that I don't see cancel-able promises becoming reality at
> any point in these days, I rather would think from scratch something better
> ( Task ? ) and leave Promises the way these are,  hoping standard bodies
> will just stop putting/using them for everything asynchronous that might
> take more than 10ms and **should** be cancelable.
>
> I'm the first one that want them  cancelable, and at this point, after
> months of discussions, the one that also doesn't see that as a solution.
>
> Best Regards
>
>
>
> On Tue, Aug 4, 2015 at 1:27 AM, Glen Huang <curvedmark at gmail.com> wrote:
>
>> @Andrea @Yad
>>
>> The only thing I'm not sure about is this "some promises have the abort
>> ability, some don't" design. It might seem clear when you first create that
>> promise, but it gets messy when you start to pass that promise around. It's
>> very easy for some function to accidentally have the ability to abort()
>> where it shouldn't.
>>
>>
>> On Aug 4, 2015, at 1:19 AM, Andrea Giammarchi <
>> andrea.giammarchi at gmail.com> wrote:
>>
>> 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:
>>
>> ```js
>> 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
>> possible
>>   fnIfAborted(function () {
>>     clearTimeout(timer);
>>   });
>> });
>> ```
>>
>> 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
>> callback.
>>
>> 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 gmail.com> 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:
>>> https://github.com/promises-aplus/cancellation-spec/issues/16.
>>>
>>> what do you think about it?
>>>
>>> 2015年8月3日(月) 8:43 Glen Huang <curvedmark at gmail.com>:
>>>
>>>> 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 mozilla.org
>>>> https://mail.mozilla.org/listinfo/es-discuss
>>>>
>>>
>>> _______________________________________________
>>> es-discuss mailing list
>>> es-discuss at mozilla.org
>>> https://mail.mozilla.org/listinfo/es-discuss
>>>
>>>
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20150804/8210a1e5/attachment-0001.html>


More information about the es-discuss mailing list