Xavier_Ex
Xavier_Ex

Reputation: 8810

AngularJS : Resolving self-chaining promises

I know that promises can be chained, as in this example:

// we also have deferA, deferB and deferC as the corresponding defer objects
promiseB = promiseA.then(function(result) {
    // do stuff to resolve B
});

promiseC = promiseB.then(function(result) {
    // do stuff to resolve C
});

Now if I call deferA.resolve(data) this will resolve promiseA, its then method will run, and then promiseB is resolved. Finally promiseB's then will run and resolve promiseC. Flat and simple (hope I got this right).

However, what happens if a promise chains with itself?

If I change the above example into this:

// we also have deferA and deferB as the corresponding defer objects
promiseA = promiseA.then(function(result) {
    // do stuff to...?
});

promiseB = promiseA.then(function(result) {
    // do stuff to resolve B
});

deferA.resolve(data);

Now what happens? What's the order of execution?

More over, what about this:

// we also have deferA and deferB as the corresponding defer objects
promiseA = promiseA.then(function(result) {
    // do stuff to...?
});

deferA.resolve(data);

promiseB = promiseA.then(function(result) {
    // do stuff to resolve B
});

What would happen in this case?

Upvotes: 1

Views: 554

Answers (1)

Benjamin Gruenbaum
Benjamin Gruenbaum

Reputation: 276596

This isn't about promises, it's about references in JavaScript.

When you do:

p = p.then(function(){...

You are changing the promise p is referring to, you are not changing the promise the deferred object will resolve when you fullfill/reject it - that's still the same p from before you re-assigned to it. So in your example code:

promiseA = promiseA.then(function(result) { // THIS WILL EXECUTE FIRST
    // do stuff to...?
});

promiseB = promiseA.then(function(result) { // THIS WILL EXECUTE SECOND
    // do stuff to resolve B
});

deferA.resolve(data);

When you attach more than one .then handler to a promise as in:

var p = first.then(...

var p2 = first.then(...

I'm assuming a Promises/A+ implementation here. The spec guarantees that both .then handlers will execute when first fulfills. It will always happen in the order they were added.

So, in the above case:

  • First promiseA will resolve
  • Then the upper promiseA.then will run (the one that was added first)
  • Then the bottom promiseA.then will run (the one that was added later)

Resolving the deferred before or after the .then addition will not change the result in a noticeable way (trivia: this is not the case with jQuery promises which is a big problem with them).


It is possible to create a circular promise chain though, just a bit harder. Just like it's possible to create an infinite loop. Good promise libraries will either run it, or throw a circular reference error.

Upvotes: 5

Related Questions