Unraveling the Event Loop

Yash DugriyalYash Dugriyal
4 min read

Mastering the JavaScript Event Loop: A Comprehensive Guide

Understanding the JavaScript Event Loop, Call Stack, and Callback Queue

JavaScript, though single-threaded, manages to handle asynchronous operations effectively through a combination of the call stack, event loop, and callback queue.

Callbacks

Now callbacks are the functions which we need to be executed only after the execution of certain functions . Now you must thinking that if javascript do the work naturally and executes synchronously then this would be easily achieved but that's not the case because there might be some functions which could take time to execute and if we execute them synchronously then there is possibility that the whole page can become inactive and non responsive to user actions which might be a very bad user experience So thats why javascript kicks of those time taking process from the main thread and gives them to underlying system or js engine to execute and moves forward in its main thread.

The Call Stack

The call stack is a data structure that follows the LIFO (Last In, First Out) principle. When a function is invoked, it's pushed onto the call stack. When the function returns, it's popped off the stack. This is how JavaScript manages synchronous code execution.

The Callback Queue

The callback queue is a data structure that stores callback functions that are waiting to be executed. When an asynchronous operation completes (like a network request, timer, or I/O operation), its callback function is placed in the callback queue.

The Event Loop

The event loop is a continuous process that monitors the call stack and the callback queue. Its primary role is to coordinate between synchronous and asynchronous code execution.

How They Work Together

  1. Synchronous code execution: When JavaScript encounters a synchronous function, it's pushed onto the call stack and executed immediately. (I guess this is easily understandable :))

  2. Asynchronous operation: When an asynchronous operation is encountered (e.g., setTimeout, fetch), it's handed off to the browser's Web APIs or Node.js's underlying system. which then takes care of its execution as the main thread moves forward with the further code.

  3. Callback registration: This asynchronous also has some callback functions which should be executed only after its execution.

  4. Callback queue: When the asynchronous operation finishes, its callback function is placed in the callback queue.(you can assume this queue as storage of functions which are yet to be executed because they were the callbacks for any of the asynchronous fucntions.)

  5. Event loop checks: The event loop continuously checks if the call stack(functions which is present in this gets immediately executed) is empty. If it is, it takes the first function from the callback queue and pushes it onto the call stack for execution.

and this is how simple the whole process of javascript execution.

If not understood then lets walk through a simple and interesting analogy ,

Imagine a busy restaurant:

  • Call Stack: The chef and kitchen staff. They handle orders one at a time. A new order comes in, they start working on it, and when it's finished, they move on to the next.

  • Event Loop: The restaurant manager. They oversee the entire operation, making sure everything runs smoothly. They check on the kitchen (call stack) and the waiting area (callback queue) regularly.

  • Callback Queue: The waiting area. Customers who arrive when all tables are occupied wait here until a table becomes free.

  • Asynchronous Operations: Customers ordering dishes that take longer to prepare, like steak or lobster. They are informed that their food will be ready later and are asked to wait in the waiting area.

How it works:

  1. New customers arrive: New orders (synchronous code) come in. The chef (call stack) starts preparing them immediately.

  2. Customers order dishes that take time: Customers order dishes like steak (asynchronous operations). They are told to wait and are added to the waiting area (callback queue).

  3. Chef finishes orders: The chef finishes preparing the quick orders and moves on to the next.

  4. Manager checks waiting area: The restaurant manager (event loop) periodically checks if any tables are free.

  5. Customers seated: When a table becomes free, the manager seats the next customer from the waiting area (callback queue).

  6. Chef prepares the dish: The chef (call stack) starts preparing the dish for the newly seated customer.

  • firstFunction is pushed onto the call stack.

  • Inside firstFunction, console.log('First function started') is executed.

  • secondFunction is called and pushed onto the call stack.

  • Inside secondFunction, console.log('Second function started') is executed.

  • setTimeout is called, but the callback is placed in the callback queue immediately due to the 0 delay.

  • console.log('Second function ended') is executed.

  • secondFunction returns, it's popped from the call stack.

  • console.log('First function ended') is executed and firstFunction is popped from the call stack.

  • The event loop finds the call stack empty and pushes the callback from the queue onto the call stack.

  • console.log('Async callback') is executed.

Hope you get it now :)

also this is a crazy good Video to understand Eventloop visually , thanx to Akshay Saini i was able to grasp this concept with more clearity.

ps: I will cover MicroTask Queue in another article.

0
Subscribe to my newsletter

Read articles from Yash Dugriyal directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Yash Dugriyal
Yash Dugriyal