JavaScript event loop, not again

Posted by Igor Borovica Friday, Jan 26, 2018
Image source (http://maxisam.github.io/2016/09/27/JavaScript-Note-Thread-Event-Loop/)

In this blog post, I'm going to talk about the JavaScript asynchronous approach. I will explain core concepts of JavaScript concurrency, a stack of frames, message queue, event loop and elements of JavaScript that make it possible to run asynchronous code in JavaScript.

Who is the target audience of this post?

This blog post is for all those interested in JavaScript, who want to learn something new about JavaScript or just renew knowledge about JavaScript. In fact, this is a post for all those who are interested in web development and JavaScript.

On the main photo, you can see how JavaScript handles asynchronous code. We have a stack, WEB APIs, message queue and event loop. I will try to explain how all of these things work together. Let's start with the stack.

The stack of frames

There are few names for the Stack of frames, like JavaScript stack, call stack or just stack. In this blog post, I'm going to use the stack of frames or stack.

For better visualization, we will start with the code example:

In this case we have three functions: add, multiply and calculate. Calculate function just calls those two functions and prints out the result. JavaScript code will be executed after the stack is full. Let’s see how the stack of frames is going to be filled.

When calling the calculate function, the first frame is pushed to the stack. After that, the add function is called and the second frame is pushed on the top of the stack. The same goes for multiply function. We can say that each frame represents a function. The stack is full, and when multiply function returns a value, the first element on top of the stack popped out of the stack, in this case, multiply function. After that add function is executed and popped out of the stack, leaving only calculate function in the stack and when the last line in the calculate function is executed, calculate function popped out of the stack and stack is now empty. We should see a result in the browser console. It's that simple.

Web APIs and JavaScript message queue

Except for JavaScript, we also have access to Web APIs which comes with a browser. Web APIs are just extra things provided by a browser. AJAX requests, DOM manipulation, timeouts and things like that and also access to event loop and message queue. Because of Web APIs, we can run JavaScript code asynchronously.

Let’s say something about JavaScript message queue. There are also few names for a message queue, like callback queue or task queue but I will use a message queue. JavaScript has built-in message queue which is a list of messages that should be executed. For easier basic understanding, message queue is holding callback functions. You can look at a message as a function which waits to be executed.

Every time you use a function to make an AJAX request or manipulate DOM with events like onClick or onEnter, that function gets pushed to the message queue where it waits to be executed, and this is where event loop comes in.

Event loop

The event loop is an infinite loop which checks if the stack is empty, and if it is, it pushes first thing from the message queue to the stack. All event loop does is wait for a message (function) in the message queue. Here is the example of event loop implementation:

Visualize this with code examples for better understanding.

First, let's see what would happen if we do not have the message queue and event loop:

In this example, we make two requests and we'll say that each request takes ten. That means that the user is going to wait for twenty seconds to make the next step on a web page and that’s not good UX. If one of these requests does not end, the user could stay forever on a web page. 

What happens if we use setTimeout function from the Web API? It is an asynchronous function which will run JavaScript code at some point in the future and give users ability to use the page while he is waiting for a response.

The setTimeout function accepts three parameters: the first one is callback function which should be executed; the second parameter is the number of milliseconds to wait before running the code, and the third parameter is additional parameters for the function. But third parameters are not important for us now. The first parameter is required, and other parameters are optional. If you omit the second parameter, the value 0 is used. Here is the result of this code example.

As you can see, the last line from our code example is executed first, and that’s because these two setTimeout functions are pushed to the message queue. There they wait to be pushed to the stack and be executed. What happened here? Because setTimeout function does not belong to JavaScript runtime and it is part of the Web API when the first setTimeout function appears, it goes to the Web API call stack and gets pushed to the message queue. After that, the same goes for the second setTimeout function, and because the last line is part of JavaScript runtime, the last line is pushed to the stack. Now event loop comes into play and repeatedly checks if the stack is empty: as soon as the stack gets empty event loop takes the first element from the message queue and passes it to the stack. That's why these two setTimeout functions are executed after the last line.

Note about setTimout function and the second parameter: the second parameter is the minimum time to execute. It does not represent the time after which the function will be executed.

I hope this blog post helped you to get more understanding of JavaScript event loop and asynchronous code execution in JavaScript. Here is a nice tool which will help you to visualize JavaScript event loop. Enjoy the video! 

comments powered by Disqus

news / events / blogs