How does JavaScript work

JavaScript is a rather specific programming language. It has both supporters and opponents but do both of you know how JavaScript exactly works?

Mateusz Bryzik
Mateusz Bryzik
Dec. 18, 201910 min read
How does JavaScript work

As you probably heard, JavaScript is a single-thread programming language. It means processed operations are handled one by one. JavaScript doesn’t have the ability to make operations parallel. We can do it in a programming language like Java, where we have the possibility to run several calculations in multiple threads. JavaScript cannot do that, it processes all the operations in sequence, so it might be very slow. But it isn’t! All of you are using very complex websites and huge web applications like Facebook. At the same time, the browser is downloading posts into our wall, we are writing and sending messages, displaying our friends’ images, clicking “Like” under them, and we don’t have any delays. It is all because of the mechanism called Event Loop.

Callstack & WebAPI

The Event Loop mechanism is closely related to the browser call stack. Call Stack is a place where goes all events created in a JavaScript application. Let’s imagine the situation when we have a button with an onClick event listener and a method that increments a counter.

$.on('button', 'click', function onClick() {
    counter += 1;
});

After clicking on this button, the invocation of the onClick method is put on the call stack. It is only a simple example but in real life, we have a huge amount of events that end up on call stack. Call stack is a data structure that follows the LIFO (Last In - First Out) rule. It means when we want to get values from the stack, we always have to take them from the top of the stack and go from up to down.

Event Loop also depends on the browser engine. Each browser engine has its own implementation of the event loop, so they may be some differences in event processing between V8, Gecko, etc. In this article, we focused on the V8 engine used in the Chrome browser and we will present event loop implementation in V8.

Event Loop behavior

In JavaScript, we can distinguish synchronous and asynchronous operations. Synchronous operations are run in the order in which they were called and they have priority. Asynchronous operations seem to be working in the background of the application, but it’s only an illusion. In the JavaScript call stack, there are put events related to synchronous operations and related to callbacks, to asynchronous ones, e.g. setTimeout or Promise.prototype.thencallback methods.

In the Event Loop mechanism, we have 3 queues: microtask queue, render queue, and task queue. Queues are working in consistence with FIFO (First In - First Out) rule. When events are removed from the call stack, they go through the whole loop.

The first checkpoint for them is a microtask queue. We put there all callbacks to methods for resolving and rejecting of Promises. The microtask queue performs all operations until it is empty. After that, the rest of the data from the call stack goes to the next stop - the render queue.

The render queue collects all tasks that need to be done before another application rendering. It is dealing with, e.g. animations. The render queue behavior is the same as the microtask queue. It evokes all operations and finishes its work when there are no more tasks.

The last element of the Event Loop sequence is the Task Queue. This queue is responsible for collecting all the callbacks to WebAPI methods like setTimeout. The behavior of Task Queue is a little bit different than the previous queues. It proceeds only with one element, performs it, and after that, the Event Loop switches back to the call stack. So even if there are some tasks left on Task Queue, it can execute only one operation.

The shortened Event Loop data flow:

  1. Take events from the call stack until it is empty.
  2. Perform subsequent operations from the Microtask Queue until it is empty.
  3. Perform subsequent operations from the Render Queue until it is empty.
  4. Perform one operation from the Task Queue.

You can also check the Event Loop behavior by running this code on Stackblitz:

function log(arg) {
    console.log(arg);
}
 
function logTimeout(number, callback) {
    setTimeout(function() {
        callback(`Timeout ${number}`);
    }, 0);
}
 
function logPromise(number) {
    return Promise.resolve(`Promise ${number}`);
}
 
logPromise(1).then(log);
logPromise(2).then(log);
logTimeout(1, log);
requestAnimationFrame(function() {
    log('RequestAnimationFrame 1');
});
requestAnimationFrame(function() {
    log('RequestAnimationFrame 2');
});
 
for(let i = 0; i < 999999; i++) {};
console.log('The end');

Being aware of how JavaScript works can help you in your daily work. Knowing that JavaScript is single-threaded can allow you to choose the right implementation and to solve many of the hazards you encountered while working with JavaScript.

 

Mateusz Bryzik
written by
Mateusz Bryzik

Frontend Developer who is crazy about new frontend technologies especially Angular and Vue.js frameworks. Analytical thinker who enjoys working with people.

Let’s get the cooperation started!

See how we can help your business become more efficient

Get started!

Find us on