5

What is a difference between:

Promise.all([1,2]) //Promise {<fulfilled>: Array(2)}

and

let p1 = Promise.all([1,2]);
console.log(p1) //Promise {<pending>}

Why does the console show a different result?

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875

1 Answers1

2

Preface: I'm assuming you pasted both lines of your second example (let p1 = Promise.all([1,2]); and console.log(p1)) at the same time; that's how I can make Chrome's console do what you've described.

Why does the console show a different result?

The important thing first up: It's a console thing. It doesn't matter to how you write your own code consuming promises. The console is doing something "magic" your code can't do: accessing the state of a promise object directly and synchronously. That lets it build and display those one-liner snapshot strings (Promise {<fulfilled>: Array(2)} and Promise{<pending>}). But your JavaScript code can't access the state of a promise directly, it can only attach fulfillment and rejection handlers to it and get that information later, asynchronously. So there's no need to worry about the difference in what you're seeing and if you like, you can just stop reading now. :-)

What's happening with the console then?

Let's look at Promise.all([1, 2]) first:

  • Promise.all loops through each element in your array
  • It wraps each element in a Promise via Promise.resolve
  • It attaches fulfillment and rejection handlers to those promises
  • It rejects its promise if any of the input promises rejects, or if all the promises are fulfilled, it fulfills its promise with an array of the results (in order)

Because the promise from Promise.all can't be settled until the Promise.all code receives notification that the promises wrapped around 1 and 2 have settled, the promise from Promise.all will always start out pending, never fulfilled. But since the promises wrapped around 1 and 2 are fulfilled, they'll do that notification as soon as possible: When the current task (the current job in the job queue) finishes. Which means the promise from Promise.all goes from being pending to being fulfilled as soon as the code you've typed/pasted into the console is done running, but not while it's running. That, combined with the "magic" thing the console is doing, explains the difference. Let's see how:

In the first example, you've just put Promise.all([1, 2]) in the console, and had the console show you the result when your code is done. That means the console sees the promise from Promise.all after your code is done running, and apparently, after the Promise.all code has received the notification that the promises around 1 and 2 have been fulfilled. So when the console sees the promise object, it sees that it's already fulfilled, so it displays a one-liner string with Promise {<fulfilled>: Array(2)}.

In the second example, though, you've pasted let p1 = Promise.all([1,2]); and console.log(p1) together, so they get processed together. That means that when console.log(p1) runs, the promise from Promise.all is still pending, because it hasn't had a chance (yet) to receive notification that the 1 and 2 promises have been fulfilled. So the console displays the one-liner string Promise {<pending>}. Then your code ends, and the promise gets fulfilled almost immediately afterward.

So it's interesting behavior, but it doesn't really matter. In both cases, the promise from Promise.all is initially pending and then is fulfilled as soon as it can be. The only reason you see the difference is that the console can "magically" see the state of a promise directly and synchronously, which our code can't.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • difficult to understand but I guess this is correct answer –  Feb 14 '23 at 16:45
  • @terminator - What parts are difficult to understand? I can try to clarify them. – T.J. Crowder Feb 14 '23 at 16:46
  • "synopsis string","microtasks","(at which point the promises wrapping the 1 and 2 process their reactions" I'm not fluent in English, –  Feb 14 '23 at 16:49
  • Is there topic related to this issue to read? –  Feb 14 '23 at 16:51
  • @terminator - I'll try to clarify the answer. But the important thing here is: The difference isn't important. It doesn't make any difference to how you write your code. It's just a console thing. :-) – T.J. Crowder Feb 14 '23 at 16:52
  • 1
    "synopsis string" how Chrome converts the promise into something readable. "microtasks" there like normal tasks like setTimout etc but with higher priority so fire before a normal task. – Keith Feb 14 '23 at 16:53
  • I know that this is not big problem and I can go on but somehow I stumbled this issue several times while learning JS Promises ;) –  Feb 14 '23 at 16:55
  • 1
    @terminator Not sure you know this, but you can actually use `await` in the chrome console. eg. `await Promise.all([1,2])` & `let p1 = await Promise.all([1,2]); console.log(p1)` – Keith Feb 14 '23 at 16:58
  • @terminator - Oh, I get why you're wondering about it. :-) I've tried to clarify the answer (and expanded it). Hope that helps! And thanks for pointing out this behavior, it's quite interesting! – T.J. Crowder Feb 14 '23 at 17:06
  • 1
    Thank your brother, T.J. Crowder for your effort. You are very kind :) –  Feb 14 '23 at 17:13