Cansu Arı Logo
Blog
What is it?

Microtask vs Macrotask in JavaScript: Truly Understanding the Event Loop

The Event Loop is not just theory! Let’s untangle Promises, setTimeouts, and task queues with real examples.

  • #JavaScript

Skip to content

Behind the Scenes of the Event Loop: Microtask vs Macrotask

JavaScript might be single-threaded, but that doesn’t mean it can only do one thing at a time. The real magic happens inside the Event Loop.

Think of the Event Loop as the heartbeat of the JavaScript engine. Code doesn’t just execute linearly—it runs according to smartly managed queues. Promises, setTimeout, and even DOM updates line up in this system. Every time you say “wait” (like during fetch requests or animations), the heartbeat ticks again.

A Simple Example

console.log('1');
setTimeout(() => console.log('2'), 0);
Promise.resolve().then(() => console.log('3'));
console.log('4');
Expected output: “1, 2, 3, 4”?

Nope. The real output: 1, 4, 3, 2

Why?

Because JavaScript has two types of task queues:
  1. Microtask Queue → Promises, queueMicrotask, etc.
  2. Macrotask QueuesetTimeout, setInterval, requestAnimationFrame, etc.
Each loop iteration does this:
  1. If the call stack is empty → run all microtasks.
  2. After microtasks → render the screen.
  3. Then move on to the next macrotask.
That’s why Promise callbacks run before setTimeout ones.

Step-by-Step Event Loop Stages

  1. Call Stack: Runs synchronous code.
  2. Microtask Queue: Fast, lightweight tasks (Promises, async/await).
  3. Render Phase: Browser paints updates to the screen.
  4. Macrotask Queue: Timers, network callbacks, I/O events.
This cycle happens dozens or hundreds of times per second. That’s why JavaScript feels concurrent, even though it’s technically single-threaded.

What Are Microtasks?

Microtasks are small but critical. They handle Promise resolutions, minor DOM updates, or jobs queued via queueMicrotask().

queueMicrotask(() => {
console.log('This runs at the end of the current event loop.');
});

They run right after the current loop iteration, before rendering. Great for tiny, immediate tasks.

⚠️ Beware of infinite microtask chains (Promise.then().then()...). They can block rendering, making your UI sluggish. 🐢

What Are Macrotasks?

Macrotasks are for “later” work—timers, events, or rendering callbacks.

setTimeout(() => console.log('Macrotask!'), 0);

Even with 0 milliseconds, this runs in the next event loop iteration. It waits for microtasks to finish. So 0 means “soon,” not “immediately.” 😊

Comparison Table

PropertyMicrotaskMacrotask
ExamplesPromise, queueMicrotasksetTimeout, setInterval, requestAnimationFrame
TimingSame event loop, before renderNext event loop iteration
Use CaseSmall, immediate jobsLarger or delayed jobs
PerformanceLow impactModerate (may delay render)
PriorityHigherLower

In Node.js

Node’s implementation is similar but with slightly different naming: process.nextTick() behaves like a microtask, while setImmediate() behaves like a macrotask.

setTimeout(() => console.log('timeout'), 0);
setImmediate(() => console.log('immediate'));
process.nextTick(() => console.log('nextTick'));

Typical output: nextTick → timeout → immediate. Node.js follows the same concept with its own queues.

Real-World Analogy

Imagine a concert stage:

  • Microtasks: The crew making quick light or sound adjustments between acts.
  • Macrotasks: The next performer waiting to go on stage.
  • Render: What the audience actually sees.

That’s why Promises (microtasks) always “perform” before setTimeout (macrotasks).

Performance and Pitfalls

  • Too many microtasks block rendering. The browser can’t “take a breath.”
  • Too many timeouts overload the CPU, causing frame drops.
  • Mixing in slight delays (setTimeout) between Promises can balance performance.

Conclusion

The Event Loop is JavaScript’s invisible engine. Understanding it lets you predict async behavior. The gap between Promise and setTimeout may seem small—but it makes a massive difference in how smooth your UI feels.

Use microtasks for fast operations, and macrotasks for scheduled or deferred work.

All tags
  • JavaScript