Cancelable promises proposal

Glen Huang curvedmark at gmail.com
Sat Aug 8 09:00:54 UTC 2015


> Note that when you attach a reaction (through the `.then()` method) to a promise that was resolved several minutes ago, the reaction will trigger: you have to somewhat stretch you mind in order to call that "reacting to state change".

What attaching callbacks through `.then()` really does is to create a new promise and attach it to the parent promise. The reaction lives in the new promise, and every new child promise without a parent promise is equivalent to having a pending parent promise. So when you attach that new promise to a resolved parent promise, I think it's reasonable to say that, from the reaction's point of view, the parent promise's state has changed.

> As I understand, promises are ideal for requesting and transmitting data without having to care much when the data is available

IMHO, that's promises's goal. How does it archive that? By reacting to parent's promise state change, which is really just a event. The only thing special about promises is that when you add event listeners, a new promise containing those listeners are returned, and the events are only filed once for each promise. Getting the data is like reading event.data.

> If you use promises for asking for data, "cancelling" is naturally akin to "reject with an abort signal as reason".

Yes, looks like akin, but is actually totally different. cancelling sends signals back to parent, rejecting sends signals down to children. The symmetry can be misleading. Able to sending signals in both directions greatly complicates the design of promises with no obvious benefits. What I'm saying is that to archive the goals that you want from cancelling, you actually don't need the ability to send signal upwards. You don't need to open that can of worms.

> The child promise that want to show disinterest should just settle itself

Are you talking about this pattern:

```
let parentPromise = asyncAction();
let cancel;
let tmpPromise = new Promise((res, rej) => {
  cancel = () => rej(new AbortError());
});
let childPromise = Promise.race([parentPromise.then(...), tmpPromise]);
childPromise.cancel = cancel;
```

This is still one way communication. So does it mean that you agree promises should be kept that way?

And basically you are giving promises the ability to resolve / reject themselves after they are created. Let me rewrite previous example with more familiar APIs:

```
let parentPromise = asyncAction();
let childPromise = parentPromise.then(...);
childPromise.reject(new AbortError()); // don't care about parent promise, let's reject the childPromise
```

This also means a grand child might have to differentiate from an abort rejection from a root promise or an ancestor promise, once you encourage this pattern.

Also, with the ignoring parent state change design, its possible to make a promise be interested its parent's state change again after it has shown disinterest. I don't think it's possible if you expose resolve / reject on created promises.

> On Aug 8, 2015, at 3:13 AM, Claude Pache <claude.pache at gmail.com> wrote:
> 
> 
>> Le 6 août 2015 à 04:20, Glen Huang <curvedmark at gmail.com <mailto:curvedmark at gmail.com>> a écrit :
>> 
>>> promises are fundamentally about chaining data together, not about listening for events.
>> 
>> IMHO, promises are more about reacting to state change and pass down that reaction. And the reaction I'm proposing to add is "no reaction will be passed down".
> 
> Note that when you attach a reaction (through the `.then()` method) to a promise that was resolved several minutes ago, the reaction will trigger: you have to somewhat stretch you mind in order to call that "reacting to state change".
> 
> As I understand, promises are ideal for requesting and transmitting data without having to care much when the data is available (be it several minutes ago or several minutes later) — which would be managing an event. On the contrary, a "state change" sounds more like an event.
> 
> The way you think of (and use) promises will influence the way you think what "cancelling a promise" and similar actions should do. If you use promises for asking for data, "cancelling" is naturally akin to "reject with an abort signal as reason".
> 
> Now concerning your original case: "let child promises show disinterest on the result of that action". The child promise that want to show disinterest should just settle itself (for example reject itself with an abort signal, but the precise outcome may depend on the reason why you want to stop listening). That will give an appropriate signal to downstream clients, and that will prevent itself from receiving messages from upstream (because a promise cannot be settled more than once). — (True, the `.then()` method doesn’t produce a promise that could be settled prematurely: you have to construct it manually. I leave that as an exercise to the reader.)
> 
> —Claude
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20150808/6d4fbeb6/attachment-0001.html>


More information about the es-discuss mailing list