← Back to list

🔄 Understanding JavaScript’s Event Loop: Microtasks vs. Macrotasks Explained

In JavaScript, asynchronous behavior is at the heart of everything — from UI rendering to network calls. However, understanding how the…

suneel sahu · 2025-06-06 09:17 · 10 claps · 2.3 min read
#javascript #event-loop #microtask-queue #js-engine
Open on Medium ↗
Wiki topics: 🌐 · Web Development

🔄 Understanding JavaScript’s Event Loop: Microtasks vs. Macrotasks Explained

In JavaScript, asynchronous behavior is at the heart of everything — from UI rendering to network calls. However, understanding how the event loop handles microtasks and macrotasks is essential to mastering JavaScript’s concurrency model.

Let’s take a deep dive through an example that uncovers exactly how and when JavaScript executes tasks — especially when both setTimeout and fetch complete at the same time.

let’s consider below example code snippet. Guess what will be console in browser.

setTimeout(() => {
  console.log("macrotask");
}, 1000);

fetch("https://api.example.com")
  .then(() => {
    console.log("microtask from fetch");
  });

console.log("sync code");

You might think that whichever asynchronous task finishes first gets executed first, and in many cases, that’s true. But what happens if both a setTimeout and a fetch (or any promise-based operation) complete at the exact same time — say, after 1000ms?

In that case, which one gets pushed to the call stack first.

Before understanding this, lets dive deep into some of the JS core concepts.

Key Concepts: Event Loop Architecture

Before answering that, let’s quickly clarify what’s happening inside JavaScript’s runtime.

Call Stack

The place where synchronous code runs, one line at a time.

Web APIs

Web APIs are browser-provided (or environment-provided, like in Node.js) background services that JavaScript can use to handle tasks asynchronously — outside the main thread. e.g., setTimeout, fetch, localStorage, IndexedDBetc.), these run operations outside the main JS thread.

Since JavaScript is single-threaded, long-running tasks (like network calls or timers) would block the entire page if handled directly. Web APIs solve this by:

  • Taking over long-running tasks, running them in the background
  • Not blocking the main thread
  • Notified via callbacks or promises when done

Remember, Web APIs Are Not JavaScript. They’re available to JavaScript in the runtime environment (e.g. browser, Node.js).

Behind the scenes:

When you call fetch():

  1. The browser’s network stack handles the HTTP request.
  2. Once the response arrives, the browser’s Promise mechanism queues the .then() in the microtask queue.
  3. The JavaScript engine picks up the task when it’s ready.

Same with setTimeout():

  1. The timer is managed by the browser (not JS engine).
  2. After the delay, the callback is put in the macrotask queue.

Macrotask Queue:

Used for timers, UI events, and I/O callbacks. for example, setTimeout, setInterval, DOM events, etc.

Microtask Queue

These are smaller tasks that are executed after the current JavaScript execution stack is empty, but before the browser proceeds to the next macrotask. Used for Promise.then(), Promise.catch(),queueMicrotask(), and MutationObserver.

Event Loop

The orchestrator that constantly checks:

  1. Is the call stack empty?
  2. Are there microtasks? Run all of them
  3. Then, pick one macrotask and run it.

Event loop run will look like this: After a macrotask starts running and finishes its synchronous code, all microtasks queued during that macrotask are executed before the next macrotask is processed.

Execution Step-by-Step

At Time = 0ms

  1. setTimeout(...) → scheduled for 1000ms later.
  2. fetch(...) → begins fetching (async) via Web API.
  3. .then(...) attached → will move to microtask queue once fetch completes.
  4. console.log("sync code") runs immediately. ✅ Output: sync code

At Time = 1000ms

Now, both:

  • setTimeout finishes → callback goes to macrotask queue
  • fetch response arrives → .then() callback goes to microtask queue

Here is the catch, when a microtask and microtask are waiting to be executed, microtask will have higher priority over macrotask.

At every tick, the event loop:

  • Runs all microtasks
  • Then executes one macrotask

so final output for above code snippet will be

sync code
microtask from fetch
macrotask

Understanding the event loop, and especially the distinction between microtasks and macrotasks, helps you predict asynchronous behavior in JavaScript — whether you’re optimizing performance, debugging async bugs, or writing UI logic.

Happy coding! 💻✨


메타데이터
post_id
2f4cf58b0836
slug
understanding-javascripts-event-loop-microtasks-vs-macrotasks-explained-2f4cf58b0836
url
https://medium.com/@sahusuneel777/understanding-javascripts-event-loop-microtasks-vs-macrotasks-explained-2f4cf58b0836
canonical_url
https://medium.com/@sahusuneel777/understanding-javascripts-event-loop-microtasks-vs-macrotasks-explained-2f4cf58b0836
author_url
https://medium.com/@sahusuneel777
status
ok
fetched_at
2026-07-11 23:07:18