Ticker

6/recent/ticker-posts

🔄 JavaScript Event Loop & Concurrency Model — Handles Multiple Tasks

JavaScript Event Loop & Concurrency Model

At some point in your JavaScript journey, you’ll hear something confusing:

“JavaScript is single‑threaded.”

Then someone shows you code doing API calls, timers, animations, and user interactions all at the same time.

So which one is true?

The answer lies in JavaScript’s event loop and concurrency model.

Once you understand how this works, async JavaScript suddenly makes a lot more sense — especially when debugging tricky timing bugs.

🧠 JavaScript Is Single‑Threaded (But Still Handles Many Tasks)

JavaScript itself runs on a single main thread.

That means it can only execute one piece of JavaScript code at a time.

Example:

console.log("Start");
console.log("Middle");
console.log("End");

Output:

Start
Middle
End

Simple and predictable.

But real applications need to handle things like:

• API requests
• timers
• user clicks
• animations

If JavaScript blocked everything while waiting for these tasks, the browser would freeze.

That’s why the event loop system exists.

⚙️ The Core Pieces Behind the Event Loop

To understand the event loop, you need to know four main components.

1️⃣ Call Stack

The call stack is where JavaScript executes functions.

function greet() {
  console.log("Hello");
}

greet();

When greet() runs:

• Function is pushed to the stack
• Code executes
• Function is removed from the stack

Only one function can run on the stack at a time.

2️⃣ Web APIs (Browser Features)

The browser provides APIs that run outside the JavaScript engine.

Examples:

setTimeout
• DOM events
fetch

These tasks are handled by the browser while JavaScript continues executing other code.

3️⃣ Callback Queue

When an async operation finishes, its callback is placed in the callback queue.

Example:

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

The timer runs in the browser environment.

When it completes, the callback waits in the queue.

4️⃣ The Event Loop

The event loop constantly checks two things:

• Is the call stack empty?
• Is there a callback waiting in the queue?

If the stack is empty, the event loop pushes the next callback into the stack.

That’s how async code eventually runs.

⏳ Example That Explains Everything

console.log("Start");

setTimeout(() => {
  console.log("Timer");
}, 0);

console.log("End");

Most beginners expect:

Start
Timer
End

But the real output is:

Start
End
Timer

Why?

Because the timer callback first goes to the callback queue, and it only runs once the call stack becomes empty.

⚡ Microtasks vs Macrotasks

Modern JavaScript actually has two queues.

Macrotask Queue

Examples:

setTimeout
setInterval
• DOM events

Microtask Queue

Examples:

• Promises (.then)
queueMicrotask

Microtasks run before macrotasks.

Example:

console.log("Start");

setTimeout(() => console.log("Timeout"));

Promise.resolve().then(() => console.log("Promise"));

console.log("End");

Output:

Start
End
Promise
Timeout

Promises run earlier because they are microtasks.

🔥 Real Developer Insight

One of the most confusing bugs I debugged early in my career came from misunderstanding the event loop. A promise callback executed before a timer I assumed would run first. Once I understood microtasks vs macrotasks, the behavior finally made sense.

Timing bugs in JavaScript often come down to event loop mechanics.

❌ Common Developer Mistakes

❌ Thinking setTimeout(fn, 0) runs instantly
❌ Ignoring the difference between microtasks and macrotasks
❌ Assuming async code runs in parallel inside JavaScript
❌ Misunderstanding how promises schedule callbacks

Understanding the event loop helps avoid subtle timing bugs.

🚀 Best Practice Summary

✅ Remember JavaScript runs on a single thread
✅ Use async APIs to avoid blocking the call stack
✅ Understand how callbacks move through the event loop
✅ Know that promises run before timer callbacks
✅ Learn the event loop to debug async timing issues

Reactions

Post a Comment

0 Comments