Cancelable promises proposal

Glen Huang curvedmark at gmail.com
Thu Aug 6 02:20:04 UTC 2015


> What you are asking for seems like a way to halt execution of the function, without ever returning from the function, or executing either branch of the try/catch

This also happens when query.done never resolves / rejects. You don't need to introduce ignore() to trigger this behavior.

I think .ignore() is more similar to

```
let timer = setTimeout(...);
clearTimeout(timer);
```

Trying to imagine setTimeout as a promise that never rejects.

> 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".

> Your code is skipped, like you wanted, but the outer promise still resolves eventually.

Yes, you can do that. But how does that relate to ignore()? The point of ignore() is to keep pending all the descendant promises. I don't think it's doable with flags when you have no idea want kind of descendant promises might be attached.

> If the same promise were returned constantly, then this would instead print `1`

Thanks for the example. This makes me realize that ignoring based on callbacks to selectively not passing down reaction to child promises is bad idea. What about making ignore() ignore parent's state change (maybe also a method to undo that)?

```
let query = queryDB(sql);
let updateView = data => render(data);
let log = data => console.log(data);
let update = query.done.then(updateView);
update.then(log);
update.ignore(); // ignore parent's state change, updateView and log will never be called
setTimeout(() => {
	update.observe() // unless keep observing parent's state change
}, timeEnoughForQueryToFinish);
```

This should work if you pass the same callbacks multiple times.

> On Aug 5, 2015, at 2:23 PM, Logan Smyth <loganfsmyth at gmail.com> wrote:
> 
> Given your example of
> 
> ```
> let done = query.done;
> done.then(updateView).then(log, logAbort);
> done.ignore(updateView);
> ```
> 
> The core of my complaint comes down to control flow. To demonstrate, let's convert this to a co generator so it's readable like sync code.
> 
> ```
> co(function*(){
>   try {
>     let result = yield query.done;
>     let update = yield updateView(result);
>     log(update);
>   } catch(err){
>     logAbort(err);
>   }
> });
> ```
> 
> What you are asking for seems like a way to halt execution of the function, without ever returning from the function, or executing either branch of the try/catch. In synchronous code the only way to achieve this would be `while(true){}`, which is terrible. There isn't really a world where I'd expect that code to execute neither side, because promises are fundamentally about chaining data together, not about listening for events.
> 
> Instead you might write your code like
> 
> ```
> let ignore = false;
> let done = query.done;
> done.then(result => ignore ? undefined : updateView(result).then(log, logAbort));
> ignore = true;
> ```
> Your code is skipped, like you wanted, but the outer promise still resolves eventually.
> 
> 
> As for the duplicate handler question, imagine this:
> 
> ```
> let counter = 0;
> function fn(){
>   return ++counter;
> }
> 
> let original = Promise.resolve();
> let result;
> for (let i = 0; i < 10; i++){
>   result = original.then(fn);
> }
> result.then(output => console.log(output));
> ```
> 
> the result is `10` because `result` was the 10th promise and then the 10th execution of `fn`. If the same promise were returned constantly, then this would instead print `1`.
> 
> 
> 
> On Tue, Aug 4, 2015 at 9:06 PM, Glen Huang <curvedmark at gmail.com <mailto:curvedmark at gmail.com>> wrote:
>> Are there some example use-cases where being able to `.ignore` is preferable to having the promise reject?
> 
> The purpose of .ignore() is to let promises show disinterest, by disinterest, i mean the situation that whatever happens to that promise, it shouldn't be observable to the callbacks. Making that promise pending forever is the correct way to do that IMO. Rejecting the promise means the callback is still interested in the rejecting case.
> 
>> I can't really see a case where you'd want to disconnect a promise handler without informing promises farther down the chain
> 
> If you want to inform promises farther down the chain, you shouldn't disconnect the handler, you should let that aborted reason flow down the chain.
> 
>> Also to your question about adding multiple handlers, if that handler has side-effects, then it would definitely cause bugs if the same promise were returned for multiple calls to `.then` with the same callback.
> 
> Are you talking about passing the same callback combination to .then() returns the same promise? Would you provide an example where it can cause bugs? I guessed it's dangerous, but not sure how it could fail. But let's say it causes bug, do you think .ignore() disconnecting all same callbacks in the current promise could cause bug too? Or it could behave counter-intuitively? I'm only using returning the same promise as a guidance on designing how ignore() works, .then() doesn't really have to behave that way.
> 
> Finally, here is an example to demonstrate the use case.
> 
> Given
> 
> ```js
> let query = queryDB(sql);
> let updateView = data => render(data);
> let log = data => console.log(data);
> let logAbort = err => {
>   if (err instanceof AbortError) console.error(reason);
>   throw err;
> };
> ```
> 
> Let's say you want to abort the query, but log the abortion in a child promise:
> 
> ```js
> query.done.then(updateView).then(log, logAbort);
> query.abort();
> ```
> 
> Or if you want to show disinterest that the query is irrelevant now:
> 
> ```js
> let done = query.done;
> done.then(updateView).then(log, logAbort);
> done.ignore(updateView);
> ```
> 
> Does this answer you question?
> 
>> On Aug 5, 2015, at 10:51 AM, Logan Smyth <loganfsmyth at gmail.com <mailto:loganfsmyth at gmail.com>> wrote:
>> 
>> Glen, sorry if this has been covered in other discussions, but it's not clear to me so I wanted to ask. Are there some example use-cases where being able to `.ignore` is preferable to having the promise reject? Promise chains are about defining flows of data and I can't really see a case where you'd want to disconnect a promise handler without informing promises farther down the chain, like your `.then(log)` in your example. To me anyway, the proposed `.ignore` seems like it adds boat-loads of complexity with unclear goals.
>> 
>> Also to your question about adding multiple handlers, if that handler has side-effects, then it would definitely cause bugs if the same promise were returned for multiple calls to `.then` with the same callback.
>> 
>> 
>> On Tue, Aug 4, 2015 at 5:32 PM, Glen Huang <curvedmark at gmail.com <mailto:curvedmark at gmail.com>> wrote:
>> 
>>> On Aug 4, 2015, at 1:32 PM, Andrea Giammarchi <andrea.giammarchi at gmail.com <mailto:andrea.giammarchi at gmail.com>> wrote:
>>> 
>>> only promises that has passed through their initialization the callback would be cancelable,and this could be reflected through a `.cancelable` property
>> 
>> That's precisely the problem. When you made a mistake and thought a function should have the ability to abort, you wouldn't reflect that `.cancelable` property, you would simply call abort(). Passing a different object makes this less likely to happen since it's not thenable.
>> 
>> 
>>> and pragmatists would never find out what should be the behavior once aborted 'cause Promise can only reject and never be ignored.
>> 
>> What do you think of the ignore() method I proposed?
>> 
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org <mailto:es-discuss at mozilla.org>
>> https://mail.mozilla.org/listinfo/es-discuss <https://mail.mozilla.org/listinfo/es-discuss>
>> 
>> 
> 
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20150806/31b20fa7/attachment.html>


More information about the es-discuss mailing list