JavaScript Event Loop & Concurrency Model
JavaScript is single-threaded, meaning it can execute one task at a time.
However, it can handle asynchronous operations using the event loop.
Understanding the event loop is essential for writing efficient and non-blocking code.
Single-Threaded Nature
JavaScript runs on a single thread with one call stack.
Long-running tasks can block the UI if not handled properly.
Call Stack
The call stack is where function execution happens.
Functions are pushed onto the stack and popped after execution.
Web APIs
Browsers provide Web APIs like setTimeout, fetch, and DOM events.
These APIs handle asynchronous operations outside the call stack.
Task Queues
- Microtask Queue (Promises, queueMicrotask)
- Macrotask Queue (setTimeout, setInterval, I/O)
Event Loop
The event loop continuously checks if the call stack is empty.
If empty, it pushes tasks from queues into the call stack.
Microtasks are processed before macrotasks.
Microtasks
Microtasks have higher priority than macrotasks.
- Promise.then()
- Promise.catch()
- queueMicrotask()
They are executed immediately after the current task.
Macrotasks
- setTimeout
- setInterval
- setImmediate (Node.js)
They are executed after microtasks are completed.
Execution Order Example
console.log('Start');
setTimeout(() => console.log('Timeout'), 0);
Promise.resolve().then(() => console.log('Promise'));
console.log('End');
Output: Start → End → Promise → Timeout
Blocking the Event Loop
Heavy synchronous tasks block the event loop and delay execution.
This can freeze the UI and degrade user experience.
Optimization Techniques
- Break long tasks into smaller chunks
- Use Web Workers for heavy computations
- Avoid blocking synchronous code
- Use async/await properly
Web Workers
Web Workers run JavaScript in background threads.
They help offload heavy tasks from the main thread.
Real-World Example
A large loop blocking the thread delays UI updates.
Splitting it into async chunks keeps the UI responsive.
Common Mistakes
- Blocking the main thread
- Misunderstanding async execution order
- Overusing setTimeout for logic control
- Ignoring microtask priority
Conclusion
The event loop is the backbone of JavaScript's asynchronous behavior.
Understanding it helps developers write efficient, non-blocking code.
Mastering this concept is essential for advanced frontend development.
Codecrown