Understanding the JavaScript Event Loop

JavaScript is a single-threaded language, which means that it can only do one thing at a time. However, it is still able to handle multiple tasks at once through the use of the event loop.

The event loop is a mechanism that allows JavaScript to run asynchronous code while still processing other code. It works by constantly checking the call stack for any pending function calls, and then executing them one by one. If a function call takes too long to complete, it gets deferred to the back of the queue and is processed later.

Browser Important Concepts

The entire runtime environment of a browser is not composed solely of the JavaScript engine. Because the language features of JS belong to a single thread, but in order to allow web pages to have functions similar to “listening for events”, “timing”, and “pulling third-party APIs”, the browser provides other parts to achieve these functions, which are:

  • Event Queue
  • Web API
  • Event Table
  • Event Loop

For the browser’s runtime environment, there are other important components in addition to the JavaScript engine, and these components work together to enable the browser to provide rich functionality and handle multiple tasks.

Among them, Event Queue, Web API, Event Table, and Event Loop are important components in the browser that can work together to handle asynchronous operations and event handlers.

Event Queue
The Event Queue is a FIFO data structure that stores events waiting to be processed. When an event occurs, it is added to the event queue and waits for processing. The event queue can store various events, such as user operation responses, timer events, network requests, and more.

Web API
Web API is a set of APIs provided by the browser for handling asynchronous operations, such as network requests, timers, local storage, and more. Web APIs are usually implemented in native code provided by the browser and are separate from the JavaScript engine. This means that when we call a Web API, the JavaScript engine delegates the task to the Web API and returns immediately without waiting for the task to complete.

Event Table
The Event Table is a data structure that stores event handlers. When an event occurs, the browser looks up the event table to determine which event handlers should be executed. The event table is usually implemented in native code provided by the browser.

Event Loop
The event loop is an infinite loop that listens to the event queue and calls the corresponding event handler. When there are events in the event queue, the event loop retrieves them and calls the corresponding event handler. The main function of the event loop is to ensure that the JavaScript engine can keep running when handling asynchronous operations, without blocking other operations in the browser.

The Call Stack

The call stack is a data structure that keeps track of the functions that are currently being executed. Whenever a function is called, it is added to the top of the call stack. When the function completes, it is removed from the stack, and the next function in line is executed.

1
2
3
4
5
6
7
8
9
10
11
function multiply(a, b) {
return a * b;
}

function add(a, b) {
let result = a + b;
result = multiply(result, result);
return result;
}

console.log(add(2, 3)); // output: 25

In the code above, the add function calls the multiply function, which in turn returns a value that is used in the add function. The call stack keeps track of the order of execution and ensures that the code runs in the correct order.

Asynchronous Code

Asynchronous code is code that runs outside of the normal call stack. This can include things like user input, network requests, and timers. When asynchronous code is executed, it is added to a separate queue known as the event queue.

1
2
3
4
5
6
7
console.log('Start');

setTimeout(() => {
console.log('Timeout');
}, 0);

console.log('End');

In the code above, the setTimeout function is used to create a timer that will run after 0 milliseconds. Despite the short delay, the function is not executed immediately. Instead, it is added to the event queue and will be executed once the call stack is empty.

The Event Loop

The event loop is responsible for monitoring both the call stack and the event queue. When the call stack is empty, the event loop takes the first function in the event queue and adds it to the call stack. This function is then executed, and any resulting functions are added to the back of the event queue.

1
2
3
4
5
6
7
8
9
10
11
console.log('Start');

setTimeout(() => {
console.log('Timeout');
}, 0);

Promise.resolve().then(() => {
console.log('Promise');
});

console.log('End');

In the code above, a Promise is used to create another asynchronous task. Despite being created after the setTimeout function, the Promise is executed first because it is added to the microtask queue, which has a higher priority than the event queue.

Conclusion

The JavaScript event loop is a powerful mechanism that allows asynchronous code to be executed without blocking the main thread. By understanding how the call stack, event queue, and event loop work together, you can write more efficient and responsive code. Remember to use asynchronous code whenever possible, and always be mindful of how your code will affect the event loop.

Author

Elliot

Posted on

2023-04-23

Updated on

2023-05-07

Licensed under