Event Loop , Stack, Queue and Heap
Event loop — concurrency model in javascript

Concurrent JavaScript: Exploring the Event Loop — PART 1

Meenu Matharu
5 min readSep 22, 2023

--

Understanding the event loop and related concepts is crucial for comprehending how JavaScript manages asynchronous operations and executes code. Let’s break down each of these terms:

Event Loop in JavaScript
Event Loop in JavaScript

1. Event Loop

The event loop is a core concept in JavaScript’s concurrency model. It’s responsible for managing the execution of code in a single-threaded environment, allowing JavaScript to handle asynchronous operations efficiently. The event loop continuously checks the call stack for tasks to execute and handles the execution of callbacks, timers, and other asynchronous events.

2. Stack

The call stack is a data structure that keeps track of function calls and their execution contexts. When a function is called, a new frame (or execution context) is pushed onto the stack. As functions complete, their frames are popped off the stack, allowing the next function in line to execute. The stack operates in a last-in-first-out (LIFO) manner.

function calculateSum(b) {
const constantA = 10;
return constantA + b + 11;
}

function multiplyAndSum(x) {
const constantY = 3;
return calculateSum(x * constantY);
}

const result = multiplyAndSum(7); // assigns 42 to result

Let’s analyze the provided code from the perspective of the JavaScript execution stack, event loop, and how it behaves like a queue:

  1. When we call the multiplyAndSum(7) function, it's like creating a stack of frames to keep track of our code's execution.
  2. The first frame, let’s call it the “multiplyAndSum frame,” is created to store references to multiplyAndSum’s arguments (in this case, x with a value of 7) and any local variables it declares.
  3. Inside the multiplyAndSum function, there's a call to the calculateSum function. This leads to the creation of a new frame, the "calculateSum frame," which is pushed on top of the "multiplyAndSum frame." The "calculateSum frame" stores references to calculateSum's arguments and local variables.
  4. The calculateSum function calculates a result and returns it. As a result, the top frame (the "calculateSum frame") is popped out of the stack, leaving us with the "multiplyAndSum frame."
  5. Now, the multiplyAndSum function computes its result and also returns it. The "multiplyAndSum frame" is popped out of the stack, leaving us with an empty stack.
  6. It’s essential to note that even though the stack is empty, the values of variables declared within these functions may still exist, as they are stored outside the stack. This allows them to be accessed by any nested functions or code that might need them even after the outer functions have returned.

So, in essence, the order of operations follows a stack-like structure where each function call creates a new frame (or stack frame) on top of the previous one, and they are popped off in reverse order as functions return their results.

3. Queue:

In a JavaScript runtime environment, there exists a message queue, essentially a list of tasks waiting to be executed. Each task is associated with a specific function responsible for handling it.

At a certain point during the event loop, the runtime begins processing the tasks in the queue, starting with the oldest one. To do this, a task is dequeued (removed) from the queue, and its corresponding function is invoked with the task as an input parameter. As always, invoking a function results in the creation of a new execution context or stack frame for that function’s execution.

The execution of these functions continues until the execution stack is empty again. Once the stack is clear, the event loop proceeds to process the next task in the queue (if any tasks remain).

4. Frame inside Stack:

A frame in the call stack represents an individual function call and its associated execution context. When a function is invoked, a frame is created and pushed onto the stack. As the function executes, variables, parameters, and the function’s execution context are stored within this frame. Once the function completes, its frame is popped off the stack.

5. Object inside Heap:

The heap is a region of memory in JavaScript where objects and data are stored. When you create objects or dynamically allocate memory (e.g., with new), they are stored in the heap.

Run to completion

In JavaScript, the “Run-to-Completion” model refers to the way in which JavaScript code is executed, ensuring that each statement is executed atomically and entirely before moving on to the next one.. Here’s an explanation of how it works:

  1. Single Threaded: JavaScript is a single-threaded language, meaning it has only one execution thread or context. This thread executes code sequentially, one statement at a time.
  2. Blocking vs. Non-Blocking: In the Run-to-Completion model, when a statement is being executed, it runs to completion before any other code can be executed. This ensures that a statement won’t be interrupted by other code.
  3. Example: Let’s consider an example with a function that takes some time to execute due to a long-running operation, like a network request or a file read. In a Run-to-Completion model, while that function is executing, no other code will run, including event handlers or callbacks. Only after the function has completed will the next statement be executed.
// A time-consuming function
function timeConsumingOperation() {
for (let i = 0; i < 1000000000; i++) {
// Simulating a time-consuming operation
}
console.log("Operation Done!");
}
timeConsumingOperation();console.log("End");

In this example, timeConsumingOperation is executed without interruption, and only after it completes does "Operation Done!" get printed, followed by "End."

  1. Async Operations: JavaScript also allows asynchronous operations through mechanisms like callbacks, promises, and async/await. These operations can be used to avoid blocking the main thread and keep the application responsive while performing tasks that might take some time.
  2. Event Loop: JavaScript utilizes an event loop to manage asynchronous tasks and callbacks. The event loop ensures that asynchronous tasks are picked up and executed when the main thread is not busy with synchronous code.

In summary, the event loop manages the execution of code in a single-threaded JavaScript environment. The stack keeps track of function calls, frames, and their execution order, while queues (such as the callback queue and message queue) store tasks and callbacks scheduled for future execution. Frames inside the stack represent individual function calls, and objects are stored in the heap and accessed through references. Understanding these concepts is essential for effective JavaScript development, especially when working with asynchronous operations.

--

--

Meenu Matharu
Meenu Matharu

Written by Meenu Matharu

🚀 Passionate Frontend Developer | Storyteller on a Coding Journey 🌟 Dive deep into the world of frontend technologies like HTML, CSS, JavaScript and React

No responses yet