Event Loop — *Why JS Is Fast Despite Being Single-Threaded*
Event Loop — *Why JS Is Fast Despite Being Single-Threaded*
🎯 After reading this lesson
By the time you finish this lesson, you'll be able to confidently handle the following three things.
- ▸✅ Event capturing, bubbling, and the delegation pattern
- ▸✅ Memory leaks caused by missing
addEventListenercleanup - ▸✅ When to apply debounce / throttle
Keep these learning goals as a checklist — once you can answer all of them, you're done with the lesson.
Single-Threaded + Event Loop
The One-Line Summary
JS is a single-threaded language that processes only one thing at a time, yet it can handle countless tasks concurrently. The secret is the Event Loop + delegating async work to the outside world.
Single-Threaded — A Trap?
If slowOperation takes 5 seconds, nothing else can run during that time. User clicks are ignored too. That's blocking.
The solution: hand off blocking work to the outside, and JS keeps moving on to the next task.
How the Event Loop Works
The browser / Node.js handles async operations (timers, network, file I/O) on separate threads. When they finish, the callback is placed in the Queue, and once the Stack is empty, the Event Loop picks it up and runs it.
The Most Famous Quiz
setTimeout(..., 0) — so why does 2 print last?
- ▸The
setTimeoutcallback goes to the Task Queue - ▸It's processed after the current code (
console.log("3")) finishes
A delay of 0 in setTimeout doesn't mean immediately — it means as soon as possible after the current code finishes.
Microtask vs Macrotask
There are 2 types of queues:
- ▸Microtask — Promise, queueMicrotask. Higher priority
- ▸Macrotask — setTimeout, events, I/O. Lower priority
Once the current code finishes:
1. All Microtasks are processed first (3)
2. Then one Macrotask (2)
Async = Delegating to the Outside
These are handled by the environment (browser / Node), not JS itself. When complete, the callback is queued. JS doesn't wait — it keeps executing the next line.
Why It's Fast
Even with 10,000 concurrent users, there's no need to spawn a separate thread per user:
- ▸Request 1 starts → DB query delegated externally → handle next request
- ▸Request 2 starts → DB query delegated → handle yet another request
- ▸DB response arrives → each callback is processed
One thread, countless concurrent operations. This is how Node.js and Nginx handle high traffic with minimal memory.
Pitfall — CPU-Bound Work
JS's async advantage applies only to I/O operations. CPU-bound work is still blocking.
Solutions:
- ▸Break it into small chunks and schedule with setTimeout
- ▸Web Worker (browser) / Worker Threads (Node) — separate thread
Summary
- ▸JS = single-threaded + Event Loop
- ▸Async work is delegated externally
- ▸Microtask (Promise) > Macrotask (setTimeout)
- ▸Strong at I/O, weak at CPU
- ▸CPU-bound work → use a Worker
⚡ Try It Yourself — Microtask vs Macrotask Order
🤖 Try asking AI like this
Knowing the concepts in this lesson lets you give AI specific instructions. Instead of a vague "fix this," you can make vocabulary-driven requests — that's the starting point for saving tokens.
- ▸"Apply a 300ms debounce to this click event"
- ▸"Add cleanup to this event handler (return () => removeEventListener)"
Why This Saves Tokens
When you don't know the concepts, you have to ask "What does that mean?" after every AI response. Those follow-up questions eat your tokens. Learn the concept once, and the conversation ends in a single exchange.