The Unsung Hero of Javascript: Event Loop and Promises
20 Mart 2025 • 6 views•
Hello, these days I am actively trying to learn and understand Javascript a little more deeply with the questions asked in the interview. Up until now, I have learned and applied almost everything in practice and I continue to do so.
After spending 5 years in the Frontend world, I set a goal for myself to learn a little more about its principles and logic. Although the questions asked in the interview seem simple, this is actually a research topic that takes hours. Because I can learn more technical topics than I expected from a single question by opening the topic. This actually helps me improve myself on the Javascript side and even learn general principles, not just Javascript.
You may have seen many articles similar to this article. But I am sure that I will try to explain a topic that you have not seen before. Let's see which titles and which keywords we will examine under the title.
What is Event Loop? Call Stack, Microtask Queue, Task Queue.
Promises and their places in Event Loop.
Sample codes.
Have you ever wondered why Promises are resolved before setTimeout? This is where Event Loop comes into play. If you are ready, let's start.
What is Event Loop?
Javascript works as a single thread and synchronously. Event Loop is a mechanism that allows Javascript to manage asynchronous operations. Event Loop comes into play when asynchronous events we do when we click on setTimeout, Promises or a button work in order and properly.
Javascript decides which piece of code to run when. It does this with the following parts:
Call Stack
Whatever code is to be run at that moment is located here. Here are console outputs, variables, functions, loops, mathematical operations, etc. These will be processed and run as they are. Then the Call Stack is emptied and asynchronous jobs are looked at later. We will examine in which order they are looked at a little later.
Task Queue
This is where asynchronous jobs are queued. Generally, jobs triggered by the browser or Node.js are here. There are setTimeout, setInterval, event handlers, DOM events etc.
Microtask Queue
It includes higher asynchronous tasks. It is usually associated with Promises. Here there are Promises, queueMicrotask, MutationObserver etc.
Here, the tracking order progresses as seen in the visual;
Has the Call Stack finished all its work? Is it empty? Yes. (Do these jobs immediately.)
Run all the jobs in the Microtask Queue. After they are finished, move on to the next step. (I have priority.)
Take care of the jobs in the Task Queue as well. (I am not in a hurry, you can do it sometime.)
Promises and Their Place in the Event Loop
Most asynchronous jobs in Javascript are done with Promises. How can we update the DOM immediately when data arrives in an API call? Or why does a Promise run before setTimeout? If we have such questions in mind, we will learn the answers to them together.
There are three states in a Promise:
Pending: The situation where the operation has not finished yet.
Resolved: The situation where the operation is successful.
Rejected: The situation where the operation is unsuccessful.
Promises process these results with methods like .then, .catch or .finally. But the main issue here is how these methods are queued in the Event Loop.
Promises belong to the Microtask Queue. In other words, when a Promise is resolved or rejected, its .then, .catch or .finally blocks are immediately added to the Microtask Queue. When the Call Stack is empty, it is an answer to the fact that the Microtask Queue will run first, so it runs before other asynchronous tasks.
We can easily say that Promises are fast and reliable when they are in the Microtask Queue. In this way, we can get the requested data earlier and provide a fast experience to the user.
console.log("1. Synchronous step");
setTimeout(() => console.log("4. I came from Task Queue"), 0);
Promise.resolve()
.then(() => console.log("2. Microtask: Promise 1"))
.then(() => console.log("3. Microtask: Promise 2"));
console.log("1.5 Synchronous step");
// 1. Synchronous step
// 1.5 Synchronous step
// 2. Microtask: Promise 1
// 3. Microtask: Promise 2
// 4. I came from Task Queue
A real example
console.log("Page is loading");
setTimeout(() => console.log("Ads loaded"), 0);
fetch("https://jsonplaceholder.typicode.com/todos/1")
.then((response) => response.json())
.then((data) => console.log("Task:", data.title));
console.log("The user is waiting");
// Page is loading
// The user is waiting
// Task: delectus aut autem
// Ads loaded
The asynchronous side of Javascript may seem confusing at first, but believe me, as time goes by and you practice, everything becomes more meaningful. In this way, you can use it easily and understand it. Now that I learned these, I said "Wow!" and this will come to mind in my next uses and I will use it more consciously.