Reputation: 5563
I noticed some interesting behavior when resolving one promise from another:
const someTask = callback => {
new Promise(res => res())
.then(() => callback())
.then(() => console.log("A 1!"))
.then(() => console.log("A 2!"));
};
new Promise(res => someTask(res))
.then(() => console.log("B 1!"))
.then(() => console.log("B 2!"));
This outputs:
B 1!
A 1!
B 2!
A 2!
My thought would be that it would:
At least enqueue one of the chains all at once so that all the A's .then
callbacks would run first followed by B's, or vice versa, however they seem to alternate back and forth which is puzzling.
Run A's first log statement before B, since it resolved before B.
I understand that this is both potentially implementation-dependent and that I shouldn't rely on execution order here (in my project I just care about A resolving B when it's done), but it intrigues me why this is happening. This is with native promises and Bluebird yields the same output.
Upvotes: 2
Views: 60
Reputation: 276306
I am going to avoid spec terminology like EnqoeueJob to not be more confusing
Whenever you .then(() => { ... })
that enqueues a microtask. Microtasks always run when there is only platform code remaining so "last" and always run before I/O.
In you case:
then
s always run on a new microtick.This means that in your case:
then
is called which fulfills the original promise.This is because microticks just schedule at the end of a microtask queue. So alternating is the "correct" behavior.
That is not implementation defined - although that was a coincidence and a mistake when building promises. You can but shouldn't rely on that order.
Upvotes: 1