9

I'm learning the Promise in js and i have some question about it, here's the code:

Promise.resolve().then(() => {
  console.log(0);
  return Promise.resolve(4);
}).then((res) => {
  console.log(res)
})

Promise.resolve().then(() => {
  console.log(1);
}).then(() => {
  console.log(2);
}).then(() => {
  console.log(3);
}).then(() => {
  console.log(5);
}).then(() => {
  console.log(6);
})

the output is far from what I expected, i thought it would be 0 1 4 2 3 5 6, because i saw this on MDN

the Promise.resolve() method returns a Promise object that is resolved with a given value

so doesn't the log() method should be triggered right behind number 1?

What am I doing wrong?

VLAZ
  • 26,331
  • 9
  • 49
  • 67
Livio
  • 300
  • 1
  • 10
  • 1
    Also even if we replace `Promise.resolve(4)` by `Promise.resolve(4).then(res=>res)`, it works the same. But anymore `then` chaining on the same pushes the `4` to be further in the output. – Lakshya Thakur May 26 '21 at 11:51
  • 1
    If we replace `Promise.resolve(4)` with `Promise.resolve(4).then(res => console.log(res));` then the order is coming as `0 1 4 ....` – Nithish May 26 '21 at 11:55

1 Answers1

2

Promises aren't being processed directly, but are based on a queue. If the promise completes, the callback is processed in the next processing cycle.

If we were to replace your code with a more verbose one, we would get:

const a = Promise.resolve('a');

const b = a.then(() => {
  console.log('b');
  const c = Promise.resolve('c');
  return c;
});

const ca = b.then((res) => {
  console.log('ca', res)
})

const u = Promise.resolve('u');

const v = u.then(() => {
  console.log('v');
});

const w = v.then(() => {
  console.log('w');
});

const x = w.then(() => {
  console.log('x');
});

const y = x.then(() => {
  console.log('y');
});

const z = y.then(() => {
  console.log('z');
});

First pass the code is running top to bottom and not a lot is going on. Two promises are being put in the queue as resolved (a and u) and nothing is printed. When those are being processed in the next cycle, they queue both b and v.

Whenever the next cycle is being processed, b is first up, logs "b" and queues the c. After that, v is processed, logs "v" and queues w.

Now, c is done, and queues the next ca (indirection, because of returning a promise in a promise), but doesn't print anything. And so on.

All the way down, it would looks something like this:

// Main tick
// - queue a
// - queue u

// Queue tick
// - resolve a, queues b
// - (log nothing)
// - resolve u, queues v
// - (log nothing)

// Queue tick
// - resolve b, queues c
// - log "b"
// - resolve v, queues w
// - log "v"

// Queue tick
// - resolve c, doesnt log, queues the next (ca)
// - resolve w, queues x
// - log "w"

// Queue tick
// - resolve x, queues y
// - log "x"
// - resolve ca, queues nothing
// - log "ca, c"

// Queue tick
// - resolve y, queues z
// - log "y"

// Queue tick
// - resolve z
// - log "z"

I'm not aware whether this is an actual requirement or not, so the order may change if the implementation (browser) decides to process promises directly. I think its unlikely though, as it doesn't encourage fairness and in case of a promise being chained forever and forever this promise would get all the resources assigned to it.

I think the general recommendation is to not depend on the order of promises being completed. Just think of a.then(b) as, b only happens after a is completed, not earlier, and nothing more.

If you require multiple promises to be dependent on each other, use Promise.all() or Promise.any().

Caramiriel
  • 7,029
  • 3
  • 30
  • 50
  • 1
    Please emphasise **the general recommendation is to not depend on the order of promises being completed**! – Bergi May 26 '21 at 13:03
  • Couple of doubts here. I don’t get why we are queuing the promises. The queuing happens for the callbacks isn’t ? Also in the third **Queue tick**, `CA` is queued before `x` but in the next tick you’re resolving `x` before `CA` ? – Lakshya Thakur May 26 '21 at 13:19
  • @LakshyaThakur Yes, the queuing is for promise jobs (resolving thenables, and executing `then` handlers on settled promises) not for "promises" themselves – Bergi May 26 '21 at 14:36