Event Loop Vizualized: Unveiling the Mysterious Enigma
As developers, we know that the heart and soul of JavaScript lies in its intricate workings. And at the core of it all, we find the Event Loop — the most important and sometimes confusing part of JavaScript. But fear not, for we have embarked on a quest to shed light on this enigmatic concept. Armed with a powerful visualization tool, we dive deep into the inner workings of the Event Loop, focusing on key concepts like console, promises, timeouts, and more.
In this article, we will dive into the event loop and explore its inner workings of how it selects and executes tasks, both asynchronously and synchronously. We’ll use a visualization tool inspired by Philip Roberts’s talk on the event loop and demonstrate its functionality with a GIF. Let’s dive in and unlock the power of JavaScript’s Event Loop together!
Javascript Snippet (1):
// Four consoles, what should be the order of execution
console.log("Hi!");
setTimeout(function timeout() {
console.log("Timeout Callback!");
}, 0);
Promise.resolve('Promise!')
.then(() => console.log('Promise Run!'));
console.log("Welcome to Event Loop.");
If we go with sync behaviour, the output of the four console should go like this:
Hi
Timeout Callback
Promise Run!
Welcome to Event Loop.
but as you can see in the gif above, output is:
Hi
Welcome to Event Loop.
Promise Run!
Timeout Callback
Both console’s will run first as you should know because of sync calls but one thing that might confuse you is why promise is called before timeout?
So, it doesn’t matter how much time we pass in timeout the output will remain same because of microtask and task queue differentiation. Microtask always executes first explained below.
Microtask Queue: The Swift Performers
First up, let’s meet the Microtask Queue — a fast-paced troupe of tasks with high priority. This queue is designed for tasks that require immediate attention, such as promises, mutation observers, and process.nextTick. These microtasks take precedence over regular tasks, ensuring their execution as soon as the call stack is clear.
Task Queue: The Diverse Ensemble
Next, we have the Task Queue — a diverse ensemble of tasks that eagerly await their turn in the spotlight. These tasks include I/O operations, timer callbacks, and other user-defined callbacks. Unlike microtasks, tasks in the Task Queue are executed after the Microtask Queue is empty. This queue forms the backbone of JavaScript’s event-driven architecture, ensuring smooth execution and allowing JavaScript to handle a wide range of tasks efficiently.
Javascript Snippet (2):
// Call Stack
function third() { }
function second() { third() }
function first() { second() }
first();
It will get executed in sequence of first -> second -> third but first’s execution will complete only and gets removed from call stack only after all the callbacks completes execution as shown in GIF above. Until then first() function is called and added to the call stack.
The Single-Threaded Nature of JavaScript:
To comprehend the event loop, it’s essential to grasp that JavaScript is single-threaded. This means that it utilizes a single thread of execution, allowing only one task to be processed at a time. However, JavaScript incorporates asynchronous behavior through browser APIs, which are built on top of the core JavaScript language and provide additional capabilities.
Heap and Stack:
In JavaScript, objects are allocated in a heap, which represents a large, mostly unstructured region of memory. On the other hand, the stack represents the single thread provided for JavaScript code execution. Function calls form a stack of frames, with each frame representing an executed function.
Understanding Browser or Web APIs:
Browser APIs are integral to web browsers and provide access to data from the browser and the surrounding computer environment. These APIs offer complex functionality, such as the Geolocation API, which allows retrieving location data. It’s crucial to note that browser APIs are not part of the JavaScript language itself but are accessible through JavaScript code. They empower developers with additional capabilities while abstracting away the underlying complexities.
Conclusion:
The JavaScript event loop is a crucial mechanism for managing asynchronous operations in JavaScript. Through the event loop, JavaScript achieves the illusion of multitasking despite being single-threaded. By visualizing the event loop and understanding its inner workings, you can effectively write asynchronous JavaScript code and handle complex scenarios.
References:
Article is heavily influenced by Philip Roberts’s talk on JS Event Loop — https://youtu.be/8aGhZQkoFbQ
Live demonstration of working of the event loop — http://latentflip.com/loupe/ created by Philip Roberts’s
Event loop Visualized in above GIF by — https://www.jsv9000.app/
Cheers! 🥂