This content originally appeared on DEV Community and was authored by Michal M.
Once every few months I do a "retest" of my JavaScript knowledge. I review sets of recruitment questions and refresh fundamentals of this language. One of the most important topics that I always review is the Event Loop. In short: it's the mechanism that allows JavaScript, despite being single-threaded, to handle asynchronous operations without blocking the main execution thread.
Because of this many of our daily problems are focused on solving the valid order of synchronous and asynchronous operations we have in our programs. That being said examples like this below and similar are quite popular during the recruitment process. At least I had this topic for a few times. I don't want to focus on explaining this problem in detail. It has already been sufficiently described in many articles by people who have much more knowledge and experience than me.
So what's the correct order of logs that will show up in the console?
console.log('First');
setTimeout(() => {
console.log('Second');
}, 0);
new Promise((res) => {
res('Third');
}).then(console.log);
console.log('Fourth');
The answers is:
First
Fourth
Third
Second
Now the explanation. While one might intuitively expect the output to be "First", "Second", "Third", "Fourth" due to the sequential reading of the code, JavaScript's asynchronous nature dictates a different order. The setTimeout
with a 0ms delay and the Promise.then
callback are not executed immediately after they are encountered. Instead, they are placed into different queues and processed by the event loop at specific times.
First console.log
is a synchronous operation and is pushed on the top of the Call stack and immediately executed.
setTimeout
is an asynchronous Web API and these operations will execute after the synchronous top-level functions. It's scheduled to be placed in the Callback Queue (Macrotask Queue) after the timer expires (which is almost immediately, but still after the current synchronous execution finishes).
Promise
is a part of Microtask Queue. These are handled with higher priority than Macrotasks. Once the current synchronous code finishes and the promise is resolved (which it already is), we will get the 'Third' logged in the console.
The last line with console.log
is another synchronous operation. It's immediately pushed onto the Call Stack and executed.
To sum up, the general order of operations is:
- Run all synchronous code on the Call Stack.
-
Drain the entire Microtask Queue. (
Promise
,MutationObserver
) -
Take one task from the Macrotask Queue and execute it. (
setTimeout
,setInterval
) - Repeat from step 1.
This content originally appeared on DEV Community and was authored by Michal M.

Michal M. | Sciencx (2025-06-20T20:48:29+00:00) Operations Order with Asynchronous JavaScript. Retrieved from https://www.scien.cx/2025/06/20/operations-order-with-asynchronous-javascript/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.