JavaScript: The Event Loop

Angus Chang
4 min readFeb 16, 2021

JavaScript is a single-threaded, asynchronous, concurrent, non-blocking language… If you’re like me this means absolutely nothing and gives you no real understanding of what JavaScript really is. But once we break down the pieces of the definition, understanding what it means may not be as arduous as it seems.

Diagram of the JavaScript Runtime
Src: Philip Roberts, What is the Event Loop Anyway?

The Runtime:

The JavaScript runtime is a V8 engine, which means it has two pieces:

The Memory Heap: This is where memory is allocated, V8 will store and delete objects and dynamic data based on when they are being used or not.

The Call Stack: This is where the stack frames are located as code executes. It is keeping track of where in the program we are. For example, if a function is called it is put on top of the call stack, once we return from a function it is popped off the call stack.

Although these are the main components when considering the V8 source there are many other aspects, that are separate from the engine but crucial for the runtime, you may be even more familiar within your day to day work:

Web APIs: APIs in your browser, such as the DOM, AJAX, setTimeout, web components, etc.

AND

The Event Loop & The Callback Queue

Single-Threaded

JavaScript is a single-threaded language, it has one call stack and means it can only do one thing at a time. One advantage of a single-threaded language is that it is simpler to deal with. This makes sense, two or more concurrent threads working incorrectly is a more complicated problem than one thread working incorrectly. Although running on a single thread can be quite limiting. While the calls stack is executing the browser is not able to do anything, meaning if there is a lengthy function in the stack it will block your app from rendering until it has returned. Imagine making a lengthy network call, once it is pushed onto the stack it will remain there until it returns like all the other processes pushed onto the stack. Only in this case, it could be a while, especially if you are making multiple network calls synchronously in a row. While we wait for the calls to return the browser will essentially be unresponsive, you may have experienced a warning like this one before:

The Solution: Asynchronous Callbacks

Asynchronous callbacks are functions that are specified to be run at a later time. Let’s take a look at the example below:

The process of the call stack starts with

  1. pushing the main function (or anonymous function, which lives in the browser)

2. push setTimeout onto the top of the stack

3. pop the setTimeout off the stack

4. push console.log(‘How are you?’) onto the stack

5. pop console.log(‘How are you?’) off the stack

6. pop the main function off the stack, the stack is now empty.

then….

7. push console.log(‘I am good’)

8. pop console.log(‘I am good’)

But what happened after the call stack was empty? How did the last console.log get pushed back on? The answer lies within the event loop:

The Event Loop and Concurrency

When we call setTimeout we pass the callback function (the console.log()) and a delay to the setTimeout call. The setTimeout call is a Web API provided by the browser. So the setTimeout call essentially gets pushed onto a separate “thread” that is provided by the browser, when these “threads” are called they are aware that concurrency has kicked in.

So when the web API is done with its task it pushes the callback function that was passed into it into something called the task queue. The task queue is just a waiting list for callback functions that have yet to run. For these callbacks to get passed back to the stack they need to be sent over by the event loop. The event loop’s job is to look at the stack and look at the task queue, whenever the stack is empty it pops a callback from the task queue onto the stack.

Non Blocking

The event loop allows for our code to be non-blocking. The entire stack will always clear before attempting to run anything in the task queue. So if you want to make an asynchronous network call you can do so knowing that your application will render regardless of how long the call takes.

Resources:

If anything still isn’t quite clicking or if you just want/need more information on the topic you should definitely check out this talk by Philip Roberts and a visualization tool he made to help folks grasp the concept.

--

--

Angus Chang

My name is Angus Chang, I am a self taught Software Developer currently working for Sparkbox and have been writing code in JavaScript and TypeScript for 3 years