EventLoop Javascript

Jose Vela's Avatar
Jose Vela
CTO Comiral
May 4, 2024

EventLoop Javascript

Have you ever wondered how the code execution process works in JavaScript? How does the language manage priority between different blocks or handle asynchronous calls while being a single thread of execution?

The key mechanism governing this behavior is the JavaScript Event Loop.

To understand its operation, it is essential to become familiar with the different components within the JavaScript execution environment.

Components of the JavaScript Execution Environment

JavaScript Engine

Since the browser cannot directly process JavaScript files, the JavaScript engine comes into play. It is the foundation of the language's operation and is composed of the heap and the call stack.

Heap

The heap is where data is stored in memory. Although its management can be complex, to simplify this explanation, we will focus on other aspects.

Call Stack

The Call Stack is where calls are stacked to execute our code. However, what happens if an operation takes too long to execute? Will the others stop? To avoid this problem, JavaScript delegates these tasks to the Web APIs.

Web APIs

When developing for the web, we encounter a variety of Web APIs that interact with the browser to resolve tasks that can take time, making them asynchronous. These tasks are completed and return in the form of callbacks or promises.

Some of the most common Web APIs are: fetch, setTimeout, DOM, localStorage, sessionStorage, HTMLDivElement, document, URL, XMLHttpRequest.

Task Queue

Calls to Web APIs that return results in the form of callbacks are lined up in the task queue. These include interactions with the DOM, HTTP requests, timers, among others.

Consider the following code block as an example:

console.log("Start of example");

setTimeout(() => {
	console.log("Wait two seconds");
}, 2000);

console.log("End of example");
  • Start of example
  • End of example
  • Wait two seconds

Upon executing this code, the console.log statements are sent directly to the Call Stack and executed, resulting in:

  1. "Start of example"
  2. "End of example"

The setTimeout function, with a delay of 2 seconds, is handled through a Web API. Once it is resolved, it is sent to the task queue for execution.

Microtask Queue

Promises, when resolved, send their handlers (.then, .catch, or .finally) to the microtask queue. These handlers are executed asynchronously, even if the promise resolves immediately. Microtasks have priority over tasks in the task queue.

For example:

let promise = Promise.resolve();

promise.then(() => alert("Promise resolved"));

alert("Code finished"); // This one executes first

Event Loop

The Event Loop is a fundamental mechanism in JavaScript that ensures asynchronous code is handled efficiently. It runs continuously, monitoring the Call Stack and the task queues (Task Queue) and microtask queues (Microtask Queue).

When the JavaScript engine encounters an asynchronous task, such as a call to setTimeout or a network operation, it delegates this task to the browser's Web APIs. Meanwhile, the JavaScript code continues to execute in the Call Stack. When the asynchronous task is completed, it is queued in the Task Queue.

This is where the Event Loop comes into play: its main function is to check if the Call Stack is empty. If it is, it takes the first task from the Task Queue and places it in the Call Stack for execution. This means that asynchronous tasks wait their turn in the queue until the Call Stack is free.

However, there is an important detail: microtasks. These have priority over normal tasks in the task queue. When the Call Stack empties, the Event Loop first takes all the microtasks from the Microtask Queue and executes them in order of arrival, before returning to the normal tasks in the Task Queue.

This behavior is crucial to ensure that promises and their handlers .then, .catch, and .finally are executed in a timely and predictable manner, even in situations where asynchronous and synchronous code are intertwined.

In summary, the Event Loop in JavaScript guarantees an orderly and efficient execution flow, prioritizing microtasks before normal tasks, and ensuring that asynchronous code is handled correctly within the context of a single thread of execution. This structure is fundamental for the development of modern web applications and the safe and effective management of asynchronous operations.

Related stories

Bare Metal is Essential for Critical Privacy

2 Feb

Bare Metal is Essential for Critical Privacy

For critical communications—encrypted messaging, patient records, or legal transcripts — cyber threats and increasingly strict data regulations are a risk and an ethical deal-breaker.

The "Noisy Neighbor" Cure

4 Jan

The "Noisy Neighbor" Cure

When one of those "neighbors" has a spike in traffic or runs a massive data-processing job, your application pays the price. This is where Bare Metal Servers step in as the ultimate cure.

Heap and memory management in JavaScript

5 May

Heap and memory management in JavaScript

Memory management varies significantly between different programming languages. In high-level languages like JavaScript, Python, or C#, memory management is automatic.