On Wed, Oct 1, 2014 at 11:44 AM, Domenic Denicola
<dome...@domenicdenicola.com> wrote:
> From: whatwg [mailto:whatwg-boun...@lists.whatwg.org] On Behalf Of Tab Atkins 
> Jr.
>
>> This is actually kinda terrible.  Promises make it *really easy* to deal 
>> with rejections *later*, letting you execute a bunch of code on the success 
>> path and only at the end saying "Oh, did something along the line fail? Let 
>> me take care of that.".  Promise is basically an async Maybe monad, which is 
>> great, because Maybe is useful for *exactly the scenario I just outlined*.
>
> This is exactly the wrong way to think about promises. Promises are the 
> "async return/throw monad"; if you want a Maybe, then you have to compose 
> that in yourself. People often try to abuse the fact that they have a second 
> branch for exceptions in order to use it as a generic container for "go down 
> two possible flow paths", but that is very incorrect. An earlier comment in 
> the thread about "we have three possible mechanisms" is also symptomatic of 
> this incorrect thinking. We have two mechanisms: return and throw. When you 
> wrap those in async, they become fulfill and reject.
>
>> I think we should develop Promises in a way that exploits their ergonomics 
>> properly, and then rethink async/await a bit to make it match those 
>> ergonomics, rather than fighting them.
>
> We are not changing the model of promises in this way. If you want a Maybe 
> monad, that's a separate API that you'd want to spec.

I've never heard this opinion explicitly expressed, and it has never
shown up in any API reviews of promise-using specs.  It's directly
contrary to the way that existing non-promise async APIs are
constructed, and I expect quite contrary to most people's
expectations.

Geo, for example, throws if you pass bad arguments, but then routes
its result through either a success or error callback.  This is
*directly* analogous to the signature of Promise.then(), and I think a
lot of people would expect a getCurrentPosition() that returned a
promise would have the same behavior.  This allows you to just assume
that the value passed to the success callback is a position, and write
code accordingly.

It feels like your position leads directly to the "error handling in
two places" problem that you, I, and others railed against in the
"promise-returning functions should never throw" debate.  You have to
handle bad arguments in the reject callback to the promise, and handle
failure in the fulfill callback.  It'll lead to a ton of boilerplate
`if(arg == null) throw;` at the top of fulfill callbacks, so that the
fulfill chain is *actually for the successful case*.

~TJ

Reply via email to