Frankie Bagnardi (2015-02-28T05:04:06.000Z)
My understanding was that it'd look like this:

// presumably standard
class CancelReason extends Error {}

// Promise.cancelable? third party library?
function cancelable(p, onCancel){
  // todo: refactor into utility function allowing: return
cancelable(resultPromise, () => {xhr.abort()})
  var doCancel;
  var cancelPromise = new Promise((resolve, reject) => {
    doCancel = reason => {
      reject(new CancelReason(reason));
      return raced;
    };
  });

  var raced = Promise.race([p, cancelPromise])
  .catch(reason => {
    if (reason instanceof CancelReason) {
        onCancel();
    }
    return Promise.reject(reason);
  });

  raced.cancel = doCancel;
  return raced;
}

function fetchAsync(url) {
  var resultPromise = new Promise((resolve, reject) => {
    xhr.open("GET", url, /*async:*/ true);
    xhr.onload = event => resolve(xhr.responseText);
    xhr.onerror = event => reject(xhr.statusText);
    xhr.send(null);
  });

  return cancelable(resultPromise, () => { xhr.abort() });
}

fetchAsync(...).then(...); // as expected
fetchAsync(...).cancel('reason').catch(...); // .catch gets the
CancelReason, and xhr is aborted
fetchAsync(...).then(...).cancel(); // TypeError .cancel is undefined

And that cancel wouldn't automatically propagate in any way; but it is a
simple callback, so can be passed around as desired.



On Fri, Feb 27, 2015 at 9:37 PM, Ron Buckton <rbuckton at chronicles.org>
wrote:

>  AsyncJS (http://github.com/rbuckton/asyncjs) uses a separate abstraction
> for cancellation based on the .NET
> CancellationTokenSource/CancellationToken types. You can find more
> information about this abstraction in the MSDN documentation here:
> https://msdn.microsoft.com/en-us/library/dd997364(v=vs.110).aspx
>
> Ron
>  ------------------------------
> From: John Lenz <concavelenz at gmail.com>
> Sent: ‎2/‎27/‎2015 8:01 PM
> To: Andrea Giammarchi <andrea.giammarchi at gmail.com>
> Cc: public-script-coord at w3.org; es-discuss <es-discuss at mozilla.org>
> Subject: Re: Cancelable promises
>
>
>
> On Fri, Feb 27, 2015 at 7:49 PM, John Lenz <concavelenz at gmail.com> wrote:
>
>> Closure Library's promise implementation supports "cancel":
>>
>>
>> https://github.com/google/closure-library/blob/master/closure/goog/promise/promise.js#L502
>>
>>  A promise is cancelled only if all the "child" promises are also
>> cancelled.
>>
>
>  I did not say that correctly, a "parent" promise can be cancelled by a
> "child" it is the only child or all the children cancel.  A parent can
> alway cancel its children (to the children this is simply "reject").  It
> does add a significant amount of complexity to the promise implementation
> but it is for the most part contained there.
>
>  I don't believe that "cancel" can be added after the fact and an
> alternative (subclass or otherwise) is needed.
>
>
>>
>> On Thu, Feb 26, 2015 at 11:43 PM, Andrea Giammarchi <
>> andrea.giammarchi at gmail.com> wrote:
>>
>>>  AFAIK bluebird did:
>>>
>>> https://github.com/petkaantonov/bluebird/blob/master/API.md#cancelerror-reason---promise
>>>
>>>  But I agree once you've made Promises more complex than events ( xhr
>>> in this case ) nobody wins :-/
>>>
>>>  Although, specially for fetch or anything network related, there
>>> **must** be a way to bloody cancel that!
>>>
>>>  ....right?
>>>
>>>
>>> On Fri, Feb 27, 2015 at 7:31 AM, Kevin Smith <zenparsing at gmail.com>
>>> wrote:
>>>
>>>> The discussion on that github issue surrounding promise subclassing
>>>> makes my head spin, especially when it comes to working out how cancelation
>>>> is supposed to flow through a graph of promise dependencies.  We should be
>>>> wary of adding complexity to the core.
>>>>
>>>> The simple way to view the situation is to say that promises are simply
>>>> transparent containers for asynchronous values. Control capabilities should
>>>> therefore be represented by a separate abstraction. This will help keep
>>>> complexity at the edges.
>>>>
>>>> Has any library experimented with the cancelation token approach yet?
>>>>  On Feb 27, 2015 1:46 AM, "Anne van Kesteren" <annevk at annevk.nl> wrote:
>>>>
>>>>> As a heads up, there's some debate around the fetch() API how exactly
>>>>> request termination should work and how that affects promises:
>>>>>
>>>>>   https://github.com/slightlyoff/ServiceWorker/issues/625
>>>>>
>>>>> The WebRTC WG has also been discussing canceling in the context of
>>>>> terminating a request for permission from the user. I think they
>>>>> decided to postpone for now until there's a bit more progress on what
>>>>> cancelable promises means, but I would not expect everyone to wait
>>>>> forever.
>>>>>
>>>>>
>>>>> --
>>>>> https://annevankesteren.nl/
>>>>> _______________________________________________
>>>>> 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
>>>>
>>>>
>>>
>>> _______________________________________________
>>> 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/20150227/8cece319/attachment-0001.html>
d at domenic.me (2015-03-06T01:17:14.886Z)
My understanding was that it'd look like this:

```js
// presumably standard
class CancelReason extends Error {}

// Promise.cancelable? third party library?
function cancelable(p, onCancel){
  // todo: refactor into utility function allowing: return cancelable(resultPromise, () => {xhr.abort()})
  var doCancel;
  var cancelPromise = new Promise((resolve, reject) => {
    doCancel = reason => {
      reject(new CancelReason(reason));
      return raced;
    };
  });

  var raced = Promise.race([p, cancelPromise])
  .catch(reason => {
    if (reason instanceof CancelReason) {
        onCancel();
    }
    return Promise.reject(reason);
  });

  raced.cancel = doCancel;
  return raced;
}

function fetchAsync(url) {
  var resultPromise = new Promise((resolve, reject) => {
    xhr.open("GET", url, /*async:*/ true);
    xhr.onload = event => resolve(xhr.responseText);
    xhr.onerror = event => reject(xhr.statusText);
    xhr.send(null);
  });

  return cancelable(resultPromise, () => { xhr.abort() });
}

fetchAsync(...).then(...); // as expected
fetchAsync(...).cancel('reason').catch(...); // .catch gets the
CancelReason, and xhr is aborted
fetchAsync(...).then(...).cancel(); // TypeError .cancel is undefined
```

And that cancel wouldn't automatically propagate in any way; but it is a
simple callback, so can be passed around as desired.