Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

when does Promise.resolve() trigger then() method? [duplicate]

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?

like image 506
Livio Avatar asked May 26 '21 09:05

Livio


People also ask

What is promise resolve () then?

resolve() The Promise. resolve() method "resolves" a given value to a Promise . If the value is a promise, that promise is returned; if the value is a thenable, Promise. resolve() will call the then() method with two callbacks it prepared; otherwise the returned promise will be fulfilled with the value.

What happens if resolve () method is called twice inside the promise executor function?

The only thing to understand is that once resolved (or rejected), that is it for a defered object - it is done. If you call then(...) on its promise again, you immediately get the (first) resolved/rejected result. Additional calls to resolve() will not have any effect.

Does promise return After resolve?

If you like this style, it can make your code a bit more compact. This works fine because the Promise constructor does nothing with any return value, and in any case resolve and reject return nothing.

Can you await a promise twice?

The implication of this is that promises can be used to memoize async computations. If you consume a promise whose result will be needed again later: consider holding on to the promise instead of its result! It's fine to await a promise twice, if you're happy to yield twice.


1 Answers

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().

like image 104
Caramiriel Avatar answered Sep 23 '22 00:09

Caramiriel