Hey JavaScript…Stop Throwing Me For a Loop!

Kelly Becker
4 min readSep 14, 2020

A Guide to Understanding What is Going On in the JavaScript Event Loop

Photo by Isabella and Louisa Fischer on Unsplash

JavaScript: A Single Threaded, Non-Blocking, Asynchronous, Concurrent Language.
That makes perfect sense…right?
Absolutely not! How is it single threaded, meaning there is only one thing happening at a time, but also non-blocking? Here is where an understanding of the event loop comes into play. JavaScript utilizes the event loop, Web API’s, and a few smart data structures, to give us the illusion of a multi threaded language. Let’s take a look at what exactly is going on!

What Makes Up the Event Loop…
The JavaScript event loop is made of a couple different components, the Call Stack and the Callback Queue.

The Call Stack
The call stack is responsible for keeping track of all the operations that need to be executed. It is a last in, first out queue. Whenever the function at the top of the stack finishes executing it is popped off the stack and the next operation in line is completed.

What exactly is happening in the above example…
1. hello() is called and pushed onto the stack
2. ‘Hello World’ is logged to the console
3. learning() is called and pushed onto the stack
4. ‘Never Stop Learning’ is logged to the console
5. learning() finishes executing and is popped off the stack
6. conclusion() is called and pushed on the stack
7. ‘The End’ is logged to the console
8. conclusion() finishes executing and is popped off the stack
9. hello() implicitly returns since it reaches the end of the function and is popped of the stack
10. The call stack is clear!

Blocking the Stack
The call stack can be blocked when slow running synchronous code, such as a synchronous network request, image processing, or an infinite loop, is pushed onto the stack. Since the operation must complete running and then be popped off the stack before the next operation can occur, this can lead to frozen web pages, button clicks that don’t register immediately, and an overall unpleasant user experience. This is where asynchronous callbacks come to the rescue, allowing us to run ‘slow code’, without blocking the call stack.

Callback Queue
The callback queue has one simple job, check when the stack is clear, when it is push the first callback in the queue onto the stack. If the callback queue is empty, just sit there and look pretty. Let’s break down an instance when the callback queue will come into play.

  1. console.log() is pushed onto the stack
  2. ‘Now’ is logged to the console
  3. console.log pops off the stack
  4. setTimeout() is pushed onto the stack
    * setTimeout is provided to us as a Web API by the browser, so when setTimeout is pushed onto the stack it fires off to the Web API to complete running.
  5. This clears the stack and allows the next console.log() to be pushed onto the stack
  6. ‘We Know’ is logged to the browser
  7. Our timer from setTimeout() has elapsed, so the callback is pushed onto the callback queue
  8. The callback queue looks and sees that the call stack is clear DRUMROLL enter the event loop. The callback is pushed onto the stack.
  9. ‘All About the Event Loop! YAY!’ is logged to the console
  10. The callback pops off the stack

When a call is made to a Web API provided to us by the browser, such as fetch, setTimeout, AJAX request, etc. A request is made to the Web API. It does not block the stack because it is being run in the browser not the JavaScript runtime. The stack is clear to do other things. The request completes(or doesn’t) and is sent back to the callback queue, where the eventual completion is determined by when the stack is clear.

And that is how JavaScript is a single threaded, non-blocking, asynchronous, concurrent language.

Recap…
1. JavaScript is single threaded, but the use of Web API’s to handle things like fetch/AJAX network requests and setTimeout/SetInterval give us the illusion of a multi-threaded language.
2. The callback queue handles these callbacks when they are returned from the Web API. Only when the call stack is clear will these callbacks be pushed onto the stack for completion. This allows us to have ‘slow code’ be non-blocking.

Check out this helpful explanation by Phillip Roberts

--

--

Kelly Becker

Solutions Engineer | Former Healthcare Clinician. You can often find me biking around the city in my sparkle helmet or pretending I’m a Top Chef