Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this Promise chain guaranteed to execute in this order?

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

let p = sleep(50);

p.then(() => console.log('a')).then(() => console.log('c'));
p.then(() => console.log('b')).then(() => console.log('d'));

Is this guaranteed to print "a, b, c, d" in that order?

As far as I can tell, "a" has to fire before "c" and "b" has to fire before "d", but beyond that, can the JS interpreter decide to execute the remainder in a different order?

like image 249
mpen Avatar asked Jan 29 '17 23:01

mpen


2 Answers

The way that things are queued using setTimeout is exactly that - a queue. If two callbacks are queued with the same 'delay', the callback that was queued first, will fire first.

Edit: I failed to understand the OP's intention initially.

'Branching' promises is what is actually occurring here. Meaning - the 'then-able' being referenced in the first set of then-ables (for a & b) will fire the two provided callbacks at 'the same time' because they both reference the same promise - however - the tricky bit is that they execute in the order that they were queued using the .then(...) of the resolving promise object.

Then the following/subsequent callbacks are queued in their respective orders (c & d).

To answer the question directly: No. The nature of the async actions in a then-able could be anything. However, the functions provided in the OP's then-ables are essentially synchronous, resulting in the intuitive - but entirely misleading - logging order.

like image 187
The Dembinski Avatar answered Oct 31 '22 03:10

The Dembinski


As far as I can tell, "a" has to fire before "c" and "b" has to fire before "d"

Yes, that much for certan.

beyond that, can the JS interpreter decide to execute the remainder in a different order?

Depends on whom you ask, but no there are more guarantees that make the output more predictable:

  • the Promise/A+ specification also demands that "all respective callbacks must execute in the order of their originating calls to then." So in your example, that means "a" has to fire before "b", because the callback was chained first to p.
  • the ECMAScript specification defines a job queue for promise callbacks, nailing down the order (imo unnecessarily). It conforms to Promises/A+ in that the "a" and "b" callbacks are queued in the order they were set up when the promise fulfills. It also means that after "a" returns and fulfills the promise, it will schedule "c", and after "b" returns and fulfills the promise, it will schedule "d", so their order is determined as well (for synchronous callbacks).

In general, don't rely on any scheduling algorithm, if you require a certain order then make it explicit.

like image 45
Bergi Avatar answered Oct 31 '22 02:10

Bergi