JavaScript Event Loop

JavaScript is one of the web’s most prominent programming languages and pretty much powers much of the web today. As I have been working on solo projects, I kind of wanted to take a deeper dive into some of the more complex nuances that the language has to offer and came across one of the most important concepts.

JavaScript has a concurrency model based on ”an event loop” and has a runtime model that consists of three pieces. They are the stack, heap, and the queue. Here is a theoretical representation of the runtime model:

The stack consists of function calls, which forms stacks or frames. Here’s an example:

function one(b) {
var a = 10;
return a + b + 11;
}

function two(x) {
var y = 3;
return one(x * y);
}

console.log(two(7)); //returns 42

When calling two(), a first stack or frame is created, containing bar’s arguments and local variables. Then when two() calls one(), a second frame or stack is created on top of bar’s stack with one()’s arguments and local variables. Then when two() returns, the top stack is popped off and removed off the stack, (leaving the initial stack intact). Then one() returns and the stack becomes empty. You can imagine them as literal boxes stacking on top of each other with labels, such as the function name and its arguments and local variables. Kind of makes it easier to visualize.

Then you have the heap, which is where objects are allocated. It is essentially a large, unstructured region of memory.

Last but not least, we have the queue also known as a message queue, which is a list of messages waiting to be processed. Each of these messages has an associated function that gets called to handle the message.

During some point of the event loop, the runtime starts handling the messages in the queue, starting with the oldest one. The message is popped off the queue and its corresponding function is called with the message as the input parameter. This calls adds to the call stack frame. This continues until the stack is empty and then the event loop continues with the next message in the queue(if there are anymore).

The event loop got its name because of how it’s implemented, which resembles this:

while (queue.waitForMessage()) {
queue.processNextMessage();
}

It waits asynchronously for a message to arrive if there is none currently. Each message is processed completely before any other message is processed. This gives some nice benefits with your program, such as whenever a function runs, it cannot be pre-empted and will run entirely before any other code runs and can modify the data the function manipulates.

There is a downside in that if the message takes too long to process, then you web application is not able to process user interactions like scrolling or clicking. You do get a browser warning that notifies you that the script is taking too long. A good practice to follow is to make message processing shorter and sort of setup a division of principles and break down complex messages into smaller, separate messages.

In web browsers, messages can be added any time an event occurs and that there is an event listener attached to the message.