Promises Consensus

Mark S. Miller erights at
Wed Jul 31 15:39:44 PDT 2013

On Wed, Jul 31, 2013 at 11:23 AM, Tab Atkins Jr. <jackalmage at>wrote:

> [Gah, resending because I'm being *way* too loose with my terminology.
>  Ignore previous email - this one has identical content, but uses
> terms correctly.] (Scratch that, I added a new point #3 at the end of
> the email.)
> [For the purposes of this email, a promise "accepting" or "rejecting"
> means that its resolver's accept() or reject() method was called, or
> the equivalent internal magic.  "fulfill" means "accept or reject".
> "resolve" means "adopt or accept, depending on whether the value is a
> promise-like or not" (in other words, what the resolver's resolve()
> method does).  "adopt" means accepting or rejecting with the same
> value as the adopted promise.  If I should be using better terms, let
> me know.]

Hi Tab, thanks for doing this. It is wonderful to have this in front of the
community and to restart the public discussion.

You say "If I should be using better terms, let me know." As is, because of
the terminology changes I find your message hard to read. (Worst for me was
' "fulfill" means "accept or reject" '.) Domenic's message is much
closer[1] to the terminology as I think of it, as the Promises/A+ community
has been using it, and as I think I've been using it in our private
discussions. I'm wondering if you could simply repost this yet again with,
approximately, Domenic's terminology? Of course, anytime Domenic's
terminology doesn't fit the distinctions you're trying to convey, do what
you need to do but note the difference. Thanks. This will make the summary
much easier for many of us to follow.

[1] One thing I think Domenic is missing that I also missed at first: Once
we introduce .flatMap, then we need a distinct "accepted" state that is
neither "fulfilled" nor "rejected". The issue is that p.then does not fire
until the promise p is fulfilled or rejected. If q is pending, and p is
accepted to q, then p.flatMap will fire but p.then will not yet fire. When
q becomes fulfilled or rejected, then p becomes fulfilled or rejected and
p.then fires. Thus, p is following q. So when p and q are both promises, p
follows q when p is accepted to q or when p adopts q. This hair splitting
goes beyond any previous conversations I've had with anyone, but becomes
necessary to account for the behavior or both .flatMap and .then under AP2.

> Heya!  I, Mark, and others have been hashing out our remaining
> differences on Promises privately, and are all happy with each other
> now, with only two remaining issues to be decided in a larger
> audience.  Anne says that we should be able to get DOM Promises on
> track with this consensus if we finish up the discussion in the next
> month or so, since the differences from the current spec are mostly
> internal/new API.
> Here's our current consensus:
> Promises have both a .then() and a .flatMap() method.
> 1. p.flatMap() does "single-level" resolution:
>     * whatever p fulfills to, gets passed to the flatMap() callbacks.
>     * The callback return value *must* be a promise-like, which is
> adopted by the output promise; otherwise, the output promise rejects
> with a TypeError.
> 2. p.then() does "recursive" resolution on the input side (per
> consensus following 2 TC39-meetings ago):
>     * if p accepts to a promise-like, the .then() callbacks get moved
> down to that promise-like until it either accepts with a
> non-promise-like, or rejects.
>     * Rejection calls the rejection callback without delay; no extra
> resolution mechanics happen here.
>     * The callback return value can be a promise-like or not.  If it
> is, the output promise adopts it; if not, the output promise accepts
> it.
> 3. The helper functions (Promise.every(), etc.) use .then() semantics.
> That is, Promise.every() will eventually accept to an array of
> non-promise-likes.
> The first issue still up for community discussion involves the
> definition of "promise-like".
> We'd like the definition to be: (a) a Promise or subtype, or (b) a
> branded non-Promise (with the branding done via Symbol or similar).
> Promises/A+ wants the branding to be done via a method named "then"
> (the "thenable" concept).
> This, unfortunately, goes directly against TC39 practices in a number
> of other areas, such as iterators, where we don't want short string
> names as branding due to the possibility of collision.  (In the case
> of "then", collision isn't a possibility, it's a certainty - we *know*
> there are libraries out there today that put a "then" method on their
> objects without referring to Promises.)  Thoughts?
> The second issue still up for community discussion is what "adopts"
> means, precisely.
> 1. Assume a .then() callback returns a non-native promise-like.  We
> can't just use magic internal operations to detect when the returned
> promise fulfills, so the output promise will have to register
> callbacks on it.  This appears to break our desire to have "lazy"
> promises in the future that don't compute a value until someone asks
> for it. Should we specify that adoption is done late?  (That is, the
> output promise would hold onto the returned promise without touching
> it, until someone actually registers some callbacks on it.)  This may
> have performance implications - is it possible that we just do eager
> resolution now, but later have detection for lazy promises getting
> returned and switch to lazy behavior in just those cases?
> 2. Assume a .flatMap() callback returns a non-native promise-like.
> Obviously, the output promise adopts it by registering .flatMap()
> callbacks on it.  But what if the promise-like only has a .then()
> method?  Should we reject with a TypeError, or fall back to using
> .then() resolution semantics?  (I suspect we need to do the former to
> maintain monad laws.)
> 3. For that matter, what about adopting the returned promise value of
> a .then() callback?  If you try and use .then() to listen for the
> returned promise to fulfill, you'll end up imposing full recursive
> semantics on the output promise, regardless of whether they're
> observed with .flatMap() or .then().  Looks like we should default to
> trying to adopt with .flatMap(), and then maybe fall back to .then()
> for .then()-returned promise-likes.
> ~TJ
> _______________________________________________
> es-discuss mailing list
> es-discuss at

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the es-discuss mailing list