Javascript Event Loop: Explained

Article Image

JAVASCRIPT

INTERVIEW

Javascript Event Loop: Explained

Browser JavaScript execution flow, as well as in Node.js, is based on an event loop. The event loop concept is very simple. There’s an endless loop, where the JavaScript engine waits for tasks, executes them, and then sleeps, waiting for more tasks.

The event loop is the secret behind JavaScript’s asynchronous programming.

Event Loop Visualization/Basic Architecture

Event Loop

Memory Heap

This is where all the memory allocation happens for your variables, that you have defined in your program.

Call Stack

This represents the single thread provided for JavaScript code execution. This is where all your javascript code gets pushed and executed one by one as the interpreter reads your program, and gets popped out once the execution is done. It is responsible for keeping track of all the operations in line to be executed. Whenever a function is finished, it is popped from the stack.

Browser or Web APIs

They are built into your web browser and are able to expose data from the browser and surrounding computer environment and do useful complex things with it. They are not part of the JavaScript language itself, rather they are built on top of the core JavaScript language, providing you with extra superpowers to use in your JavaScript code.

For example, the Geolocation API provides some simple JavaScript constructs for retrieving location data so you can say, plot your location on a Google Map. In the background, the browser is actually using some complex lower-level code (e.g. C++) to communicate with the device’s GPS hardware (or whatever is available to determine position data), retrieve position data, and return it to the browser environment to use in your code. But again, this complexity is abstracted away from you by the API.

Common browser APIs

  • APIs for manipulating documents
  • APIs that fetch data from the server
  • Audio and Video APIs
  • Client-side storage APIs

Event or Callback Queue

This is where your asynchronous code gets pushed to, and waits for the execution.

Event Loop

It has one simple job to monitor the call stack and the callback queue. It keeps running continuously and checks the Main stack, if it has any frames to execute, if not then it checks Callback queue, if Callback queue has codes to execute then it pops the message from it to the Main Stack for the execution.

Job Queue or Microtask Queue

Apart from Callback Queue, browsers have introduced one more queue which is “Job Queue”, reserved only for new Promise() functionality. So when you use promises in your code, you add .then() method, which is a callback method. These thenable methods are added to Job Queue once the promise has returned/resolved, and then gets executed.

Execution of async function in javascript

Whenever an async function is called, it is sent to a browser API. These are APIs built into the browser.

An example of this is the setTimeout method. When a setTimeout operation is processed, it is sent to the corresponding API which waits till the specified time to send this operation back in for processing.

This operation is then send to the callback queue. Hence, we have a cyclic system for running async operations in JavaScript. The language itself is single-threaded, but the browser APIs act as separate threads.

The event loop facilitates this process. It has one simple job to monitor the call stack and the callback queue. If the call stack is empty, the event loop will take the first event from the queue and will push it to the call stack, which effectively runs. If it is not, then the current function call is processed.

const foo = () => console.log("First");
const bar = () => setTimeout(() => console.log("Second"), 500);
const baz = () => console.log("Third");

bar();
foo();
baz();

Output:
First
Third
Second

Callback Queue

Why Job Queue or Microtask Queue

Micro-tasks has high priority in executing callbacks, if event loop tick comes to Micro-tasks, it will execute all the jobs in job queue first until it gets empty, then will move to callback queue.

  • The primary reason for prioritizing the micro-task queue is to improve the user experience.
  • Micro-tasks include mutation observer callbacks as well as promise callbacks.

micro-task Queue

Example:

console.log('Message no. 1: Sync');

setTimeout(function() {
   console.log('Message no. 2: setTimeout');
}, 0);

var promise = new Promise(function(resolve, reject) {
   resolve();
});

promise.then(function(resolve) {
   console.log('Message no. 3: 1st Promise');
})
.then(function(resolve) {
   console.log('Message no. 4: 2nd Promise');
});

console.log('Message no. 5: Sync');

// Message no. 1: Sync
// Message no. 5: Sync
// Message no. 3: 1st Promise
// Message no. 4: 2nd Promise
// Message no. 2: setTimeout

All thenable callbacks of the promise are called first, then the setTimeout callback is called.

References:

Thanks for reading!!!

No comments:

Post a Comment

The Importance of Cybersecurity in the Digital Age

 The Importance of Cybersecurity in the Digital Age Introduction: In today's digital age, where technology is deeply intertwined with ev...