Event Loop and promises

Viewed 51

When I am running below code in the console, I am getting output as:

"start"
"Promise 2"
"end"
"Promise 1"

console.log("start");
Promise.resolve().then(
  () => console.log("Promise 1")
).then(console.log("Promise 2"));
console.log("end");

Can anyone explain to me why "Promise 2" is printed before "Promise 1" and "end"?

2 Answers

The argument to .then() should be a function. But you wrote .then(console.log("Promise 2")), and console.log("Promise 2") is a function call, not a function. It's executed immediately, so the log message is displayed immediately, not when the promise is resolved.

Change it to a function, like you have around console.log("Promise 1"), and they'll be executed in the expected order.

console.log("start");
Promise.resolve().then(
  () => console.log("Promise 1")
).then(() => console.log("Promise 2"));
console.log("end");

end is logged first because promise resolution is asynchronous.

As pointed out, you should pass console.log as a function to have it run in the correct order.

As for the reason for end displaying first, it is because the event loop will make sure the call stack is empty and all global executions are complete before it checks the micro-task queue (sometimes called the job queue) where your console logs are sitting waiting to be added to the call stack.

It's about priorities (in descending order of priority):

  • Global thread of execution
  • Micro-task/job queue
  • Task queue

The start and end are in the global thread of execution so will run first. The event loop will then add Promise 1 and Promise 2 logs from the micro-task queue and run them after all global executions are finished. Finally if the micro-task queue is empty, the event loop will check the task queue (things like setTimeout get added here).

Hope that helps.

Related