JavaScript's Event Loop: Macrotasks & Microtasks

The JavaScript event loop processes tasks like setTimeout callbacks or user clicks from a macrotask queue. A single, long-running macrotask blocks all rendering and user input, freezing the UI. The footgun is assuming setTimeout(fn, 0) runs instantly.
Why it exists
JavaScript runs on a single thread, meaning it can only do one thing at a time. To handle concurrent operations like user input, network requests, and timers without blocking, it uses an event loop to manage a queue of tasks. This system allows a single thread to remain responsive by processing events and executing code in an orderly, non-blocking fashion.
The mental model
Think of the event loop as a manager with a to-do list called the macrotask queue. It picks the oldest task, works on it until it's completely finished, and only then looks at the list again. While it's working on a task, it's completely deaf to new user events or timers. The browser can't even repaint the screen. This is why a single long task freezes the page.
How it works
The JS engine runs an endless loop. When the main call stack is empty, it checks the macrotask queue. If a task is present (e.g., a setTimeout callback is due, a user clicked a button), it pulls that task off the queue and executes it. Any new macrotasks that arrive while one is running are added to the end of the queue. There is also a separate, higher-priority microtask queue (for things like Promise resolutions), but macrotasks are the primary mechanism for handling events, scripts, and rendering.
When to use it
You actively manage the macrotask queue when you have a CPU-intensive operation that would block the main thread. For example, processing a large dataset, performing complex calculations, or syntax-highlighting a large block of code. By breaking the task into smaller pieces and scheduling each piece with setTimeout(fn, 0), you yield control back to the event loop periodically, allowing the UI to stay responsive.
When not to use it
Don't split trivial, fast operations into macrotasks. The overhead of setTimeout (creating a timer, queueing a task) would make the code slower and more complex for no benefit. This technique is specifically for long-running, synchronous code that would otherwise cause the UI to become unresponsive. It is a solution for unblocking the main thread, not a general-purpose tool for all functions.
One canonical example
A function needs to count from 1 to 1,000,000,000. A simple for loop will execute as a single, massive macrotask, freezing the browser for seconds and potentially triggering a "Page Unresponsive" warning. The correct approach is to split the work. A function can count 1,000,000 times, then use setTimeout(count, 0) to schedule the next million counts. This creates 1,000 separate macrotasks. Between each one, the browser is free to process user input and render updates, keeping the UI alive.
Interview question
What is the primary benefit of splitting a CPU-intensive synchronous operation into smaller pieces using setTimeout(fn, 0)?
- a.To ensure the entire operation completes faster by leveraging asynchronous execution.
- b.To allow the browser to process UI updates and user input between task segments.Correct
- c.To execute each piece of the task in parallel, improving overall performance.
- d.To guarantee that each piece runs immediately after the previous one, without any delay.
Why? this is the answer
The card states that splitting work with setTimeout(fn, 0) allows yielding control back to the event loop, enabling the browser to process user input and render updates, keeping the UI alive. Option A is incorrect because this technique adds overhead and does not necessarily speed up the overall execution time; its purpose is responsiveness, not raw speed.
Just read this? Test yourself on what you have been reading.
Read the original → javascript.info
- #event loop
- #node.js
- #async
- #performance
Put your scrolling time to good use
Learn one idea, try a quiz and save useful cards for revision. Tezvyn makes it easy to learn and stay current in your tech field, a few minutes at a time.
The iPhone app is on the way
We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.
Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.
We are hiring for this. Every open role lists the topics its interview covers, so you can prepare for the real thing rather than guessing.
See open roles