
Understand the JavaScript event loop in depth. Learn how the call stack, microtasks, and macrotasks work together to handle asynchronous code efficiently, keeping your applications fast, predictable, and responsive.
Martin Ferret
November 18, 2025
JavaScript runs on a single thread. You can think of it as a single-lane road where only one car, one piece of code, can drive at a time.
That car represents the call stack, the place where your currently executing functions live.
When a car needs to stop for gas, for example when a function triggers an asynchronous operation like fetch() or setTimeout(), it doesn’t block the entire road. It simply pulls over. Other cars can continue driving.
Once the gas is ready, the car rejoins the traffic flow through one of two queues: the microtask queue (for Promises, queueMicrotask, or MutationObserver) or the macrotask queue (for setTimeout, setInterval, or DOM events).
The event loop acts as the traffic controller.
It continuously checks if the road is clear. When it is, it takes the next waiting car from the queues and lets it pass, always giving priority to microtasks before macrotasks.
This system is what allows JavaScript to appear asynchronous, even though it never runs more than one task at a time.
The JavaScript runtime is built around three essential structures.
The Call Stack
This is where synchronous code executes. Each function call is pushed onto the stack and popped off when it completes.
The Heap
A large region of memory where objects, closures, and references are stored.
The Queues
These hold asynchronous tasks waiting to run once the call stack is empty.
The event loop monitors all of these. It ensures that tasks are processed in the right order, that the main thread never stays idle, and that asynchronous operations never block execution.
To understand how asynchronous code executes, you need to distinguish between microtasks and macrotasks.
Microtasks such as Promises and queueMicrotask are executed immediately after the current stack clears, before the next rendering cycle. They have higher priority and will always run before any macrotask begins.
Macrotasks such as timers, events, or I/O operations run after all microtasks have finished. Each macrotask represents a new “tick” of the event loop.
Example:
console.log('Start');
setTimeout(() => console.log('Macrotask: Timeout'), 0);
Promise.resolve().then(() => console.log('Microtask: Promise'));
console.log('End');
Output:
Start
End
Microtask: Promise
Macrotask: Timeout
The promise callback executes before the timeout because microtasks are always processed first.
Consider a common UI pattern. When a user clicks a button, you show a loading message and then fetch data from an API.
button.addEventListener('click', () => {
list.textContent = 'Loading...';
fetch('/api/items')
.then(res => res.json())
.then(data => {
list.textContent = data.join(', ');
});
});
The text “Loading…” appears immediately because setting it is a synchronous operation.
The fetch() call runs asynchronously, and when the data is ready, the promise resolves and updates the DOM.
The event loop coordinates this without freezing the interface or blocking user interaction.
Understanding the event loop is essential for writing efficient JavaScript.
Performance
It helps you prevent blocking operations that slow down rendering or user input.
Predictability
It allows you to reason about task order, avoiding subtle async timing bugs.
Frameworks
Every modern frontend or backend framework such as React, Angular, or Node.js relies on the event loop’s scheduling model.
Control
Once you understand microtask and macrotask behavior, you can deliberately control when and how asynchronous code runs.
The event loop is the heartbeat of the JavaScript runtime. It manages everything that happens, from synchronous calls to asynchronous operations, one step at a time.
When you master how it moves between the stack, microtasks, and macrotasks, asynchronous JavaScript stops feeling random. It becomes predictable, transparent, and fully under your control.
Get the latest news and updates on developer certifications. Content is updated regularly, so please make sure to bookmark this page or sign up to get the latest content directly in your inbox.

Inside the JavaScript Event Loop: How the Runtime Actually Works
Understand the JavaScript event loop in depth. Learn how the call stack, microtasks, and macrotasks work together to handle asynchronous code efficiently, keeping your applications fast, predictable, and responsive.
Martin Ferret
Nov 18, 2025

React Free Weekend: 48 hours of Open Access to Premium React Certification Training
Every year, we at Certificates.dev look for ways to make our certifications more accessible - not just for teams inside big tech companies, but for every developer who wants to validate their skills through real-world, hands-on learning. That’s why we are excited to announce our first-ever React Free Weekend, taking place on November 15–16, 2025.
Aurora Scharff
Nov 11, 2025

Error Handling in React with react-error-boundary
Learn how to handle errors in React applications with react-error-boundary. Explore fallback UIs, async error handling with useErrorBoundary, and React 19's automatic error boundary integration with form actions and useTransition.
Aurora Scharff
Nov 10, 2025
We can help you recruit Certified Developers for your organization or project. The team has helped many customers employ suitable resources from a pool of 100s of qualified Developers.
Let us help you get the resources you need.
