Promise/Future: asynchrony in 'then'

Tab Atkins Jr. jackalmage at
Wed May 1 08:51:25 PDT 2013

On Tue, Apr 30, 2013 at 9:43 AM, Claus Reinke <claus.reinke at> wrote:
> The promises-aplus spec has a note that confuses me
>    1. In practical terms, an implementation must use a mechanism such    as
> setTimeout, setImmediate, or process.nextTick to ensure that    onFulfilled
> and onRejected are not invoked in the same turn of the    event loop as the
> call to then to which they are passed.
> I have not yet been able to decide whether DOMFuture has a
> similar provision, or how this note is meant to be interpreted.

Juan already pointed out the "queue a task" language, so this is answered.

> The aspect that worries me is that this note is attached not to the
> creation of promises but to the definition of 'then'. Is that because
> of the implicit return lifting (if 'then' callbacks do not return promises,
> wrap the return in a new promise), or is there something else going on?

Yes.  The promise itself may be fulfilled synchronously - the resolver
callback is called immediately, and can immediately call
"r.accept(val)" if it wants.  The important part is that chained
callbacks (through .then(), .done(), etc.) be handled async.

> As long as the 'then' callbacks return Promises, the idea of resolved
> Promise creation as left and right identity of 'then'
>    Promise.of(value).then(cb) = cb(value)
>    promise.then(Promise.of) = promise
> would seem to require no additional delays introduced by 'then' (promise
> creation decides semantics/delays, 'then' only passes on intermediate
> results).
> Could someone please clear up this aspect? How is that note meant
> to be interpreted, and do other Promise/Future specs have similar
> provisions?
> Claus
> PS. Prompted by this blog post:

The reason you want to maintain asynchrony, even when it's possible to
go ahead and run callbacks async, is so that the operation of futures
is *predictable*.  It doesn't matter (and it's unobservable) whether a
future is pending or fulfilled - you just attach a callback to it, and
it'll run no earlier than the next event-loop tick, so the rest of the
code in your function can depend on the fact that it hasn't run yet.
If it sometimes runs synchronously, then you can't depend on that -
the rest of the code in your function may be assuming that certain
outside variables don't change, but the promise might tweak them
synchronously, or might leave them alone until it runs async.


More information about the es-discuss mailing list