The JavaScript Event Loop Explained

JavaScript Logo

JavaScript is a single-threaded language, meaning it can only do one thing at a time. However, it can handle asynchronous operations like API calls or timers without freezing the user interface. This is made possible by the Event Loop.

The Core Components

  • Call Stack: Where JavaScript keeps track of function calls. When a function is called, it's added to the stack. When it returns, it's popped off.
  • Web APIs / C++ APIs (in Node.js): These are provided by the browser or Node.js. Asynchronous operations (like `setTimeout` or `fetch`) are handed off to these APIs to be handled outside of the main JavaScript thread.
  • Callback Queue (or Task Queue): When an asynchronous operation is complete, its callback function is placed in the Callback Queue.
  • Event Loop: The Event Loop's job is simple: it constantly checks if the Call Stack is empty. If it is, it takes the first item from the Callback Queue and pushes it onto the Call Stack, to be executed.

Example Walkthrough

console.log('Start');

setTimeout(() => {
  console.log('Inside Timeout');
}, 0);

console.log('End');

Execution Order:

  1. `console.log('Start')` is pushed to the Call Stack and executed. Output: 'Start'.
  2. `setTimeout` is pushed to the Call Stack. It's an async operation, so it's handed off to the Web API, which starts a 0ms timer. `setTimeout` is then popped from the stack.
  3. `console.log('End')` is pushed to the Call Stack and executed. Output: 'End'.
  4. The timer finishes almost instantly. The callback `() => { console.log('Inside Timeout'); }` is placed in the Callback Queue.
  5. The Event Loop sees the Call Stack is now empty. It takes the callback from the queue and pushes it to the stack.
  6. The callback is executed. Output: 'Inside Timeout'.

This is why asynchronous callbacks always run after the synchronous code has finished, even with a timeout of 0ms.

Comments