- From: Tab Atkins Jr. <jackalmage@gmail.com>
- Date: Wed, 1 Oct 2014 11:59:01 -0400
- To: Domenic Denicola <domenic@domenicdenicola.com>
- Cc: Andrew Wilson <atwilson@google.com>, WHATWG <whatwg@whatwg.org>, Jake Archibald <jaffathecake@gmail.com>, Peter Beverloo <beverloo@google.com>, Jonas Sicking <jonas@sicking.cc>
On Wed, Oct 1, 2014 at 11:44 AM, Domenic Denicola <domenic@domenicdenicola.com> wrote: > From: whatwg [mailto:whatwg-bounces@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
Received on Wednesday, 1 October 2014 15:59:46 UTC