How the Call Stack, Event Loop, and Callback Queue Work Together

In JavaScript, the call stack, event loop, and callback queue are key concepts that help the language handle code execution, especially when dealing with asynchronous tasks like fetching data from a server. Here’s an easy explanation of each:

1. Call Stack (The Task Manager)

The call stack is like a to-do list for the JavaScript engine. It keeps track of which function is currently being executed and what function will run next.

How It Works:

  • When you call a function, it gets added to the top of the stack.

  • Once the function finishes, it gets removed from the stack, and the next function can run.

Example:

javascriptCopy codefunction greet() {
  console.log("Hello");
}

function sayGoodbye() {
  console.log("Goodbye");
}

greet();     // "greet" is added to the call stack
sayGoodbye(); // "sayGoodbye" is added after "greet" finishes

2. Event Loop (The Traffic Controller)

The event loop is like a traffic controller that makes sure tasks from the call stack are executed first, and then it checks the callback queue to see if any new tasks need to be executed.

JavaScript is single-threaded, meaning it can only do one thing at a time. The event loop ensures that asynchronous tasks (like fetching data) don't block other code from running. It constantly checks:

  1. Is the call stack empty?

  2. If yes, it looks into the callback queue and sends tasks from there to the call stack for execution.

3. Callback Queue (The Waiting Room)

The callback queue is a holding area for tasks that are waiting to be run. These tasks usually come from asynchronous operations like setTimeout, network requests, or event listeners.

When an asynchronous task completes, it doesn't go directly to the call stack. Instead, it goes to the callback queue and waits for the event loop to send it to the call stack once the stack is empty.

Putting It All Together

Imagine you order pizza (an asynchronous task). The pizza will arrive later (callback), but while you're waiting for the pizza, you continue doing other tasks (call stack) like watching TV. Once the pizza arrives, you can eat it (callback gets executed), but only when you’re done with your current task.

Example with setTimeout (Asynchronous Task):

javascriptCopy codeconsole.log("Start");

setTimeout(() => {
  console.log("This runs later");
}, 2000);  // After 2 seconds, this goes to the callback queue

console.log("End");

Here’s what happens:

  1. "Start" goes to the call stack and is logged.

  2. setTimeout starts but doesn’t block other code. After 2 seconds, the callback (console.log("This runs later")) moves to the callback queue.

  3. "End" is logged next because it's on the call stack.

  4. After the call stack is empty, the event loop picks up the callback from the callback queue and executes it.

Visual Summary:

  • Call Stack: Runs the functions in order.

  • Callback Queue: Holds tasks that are waiting to be run (like after an asynchronous event).

  • Event Loop: Moves tasks from the callback queue to the call stack when the stack is empty.

This system allows JavaScript to be non-blocking, meaning it can handle tasks efficiently even when waiting for things like data from a server.

Did you find this article valuable?

Support Abhishek Mukherjee by becoming a sponsor. Any amount is appreciated!