0

I am wondering whether the following is defined behavior per the Promise specification:

var H = function (c) {
  this.d_p = Promise.resolve();
  this.d_c = c;
};

H.prototype.q = function () {
  var s = this;
  return new Promise(function (resolve) {
    s.d_p = s.d_p.then(function () {       // (1)
      s.d_c({
        resolve: resolve
      });
    });
  });
};

var a,
    h = new H(function (args) { a = args; }),
    p;

Promise.resolve()
.then(function () {
  p = h.q();
})
.then(function () {                        // (2)
  a.resolve(42);
  return p;
});

The question is whether it's guaranteed that the then callback marked (1) is called before the then callback marked (2).

Note that both promises in question are instantly resolved, so it seems to me like the (1) then callback should be scheduled as part of calling h.q(), which should be before the promise used to resolve (2) is resolved, so it should be before (2) is scheduled.

An example jsfiddle to play about with: https://jsfiddle.net/m4ruec7o/

It seems that this is what happens with bluebird >= 2.4.1, but not prior versions. I tracked the change in behavior down to this commit: https://github.com/petkaantonov/bluebird/commit/6bbb3648edb17865a6ad89a694a3241f38b7f86e

Thanks!

dharesign
  • 3
  • 1
  • No, they are unrelated, so there are no guarantees. If you care about execution order, you will need to chain them explicitly to each other. – Bergi May 25 '16 at 17:12
  • It is guaranteed that `h.q()` will get called before `a.resolve(42)`. It's not guaranteed what order things that are chained off a new promise inside of `h.q()` will happen in. Independent promise chains (that are not linked) have no specified execution order and, in fact, my testing has shown that the execution order of independent chains does vary from one environment to another. – jfriend00 May 25 '16 at 17:12
  • What is this weird `H` thing anyway? If you could tell us what problem you are trying to solve, we might be able to come up with a proper solution for you. – Bergi May 25 '16 at 17:14
  • I guess you are missing a return statement. After p = h.q(); you should do return p; – Alessandro Loziobiz Bisi May 25 '16 at 21:09
  • @Bergi: `H` is a handle to some resource, where calls to `q` need to be serialized. @AlessandroLoziobizBisi: No, the missing return is deliberate. This is what the mock version currently looks like. The callback passed into the constructor of `H` is used to inspect the call to `q`. In this case it simply used to initialize the `a` variable with an object which allows the promise `p` to be resolved at a specific point. – dharesign May 26 '16 at 10:06
  • @dharesign: Ah, I begin to understand. You should [avoid the `Promise` constructor antipattern](http://stackoverflow.com/q/23803743/1048572) though, and that `d_c` callback should be a promise-returning function instead of taking a `resolve` object as its parameter. The `q` method then simplifies to `return this.d_p = this.d_p.then(this.d_c);`. – Bergi May 26 '16 at 12:46

1 Answers1

0

You can guarantee that h.q() will be called before a.resolve(42); is called because chained .then() handlers do execute in order.

If you were asking about code within h.q(), then s.d_p.then() is part of a completely different promise chain and promise specifications do not provide ordering for separate promise chains. They are free to execute with their own asynchronous timing. And, in fact, I've seen some differences in the execution of independent promise chains in different Javascript environments.

If you want to direct the execution order between two independent promise chains, then you will have to link them somehow so one operation does not run until some other operation has completed. You can either link the two chains directly or you can do something more complicated involving an intermediate promise that is inserted into one chain so it blocks that chain until it is resolved.

You may find this answer useful What is the order of execution in javascript promises which provides a line by line analysis of execution order of both chained and independent promises and discusses how to make execution order predictable.

Community
  • 1
  • 1
jfriend00
  • 683,504
  • 96
  • 985
  • 979