DEV Community

Cover image for  ✨♻️ JavaScript Visualized: Event Loop
Lydia Hallie
Lydia Hallie

Posted on • Updated on

✨♻️ JavaScript Visualized: Event Loop

Oh boi the event loop. It’s one of those things that every JavaScript developer has to deal with in one way or another, but it can be a bit confusing to understand at first. I’m a visual learner so I thought I’d try to help you by explaining it in a visual way through low-res gifs because it's 2019 and gifs are somehow still pixelated and blurry.

But first, what is the event loop and why should you care?

JavaScript is single-threaded: only one task can run at a time. Usually that’s no big deal, but now imagine you’re running a task which takes 30 seconds.. Ya.. During that task we’re waiting for 30 seconds before anything else can happen (JavaScript runs on the browser’s main thread by default, so the entire UI is stuck) 😬 It’s 2019, no one wants a slow, unresponsive website.

Luckily, the browser gives us some features that the JavaScript engine itself doesn’t provide: a Web API. This includes the DOM API, setTimeout, HTTP requests, and so on. This can help us create some async, non-blocking behavior 🚀

When we invoke a function, it gets added to something called the call stack. The call stack is part of the JS engine, this isn’t browser specific. It’s a stack, meaning that it’s first in, last out (think of a pile of pancakes). When a function returns a value, it gets popped off the stack 👋

The respond function returns a setTimeout function. The setTimeout is provided to us by the Web API: it lets us delay tasks without blocking the main thread. The callback function that we passed to the setTimeout function, the arrow function () => { return 'Hey' } gets added to the Web API. In the meantime, the setTimeout function and the respond function get popped off the stack, they both returned their values!

In the Web API, a timer runs for as long as the second argument we passed to it, 1000ms. The callback doesn’t immediately get added to the call stack, instead it’s passed to something called the queue.

This can be a confusing part: it doesn't mean that the callback function gets added to the callstack(thus returns a value) after 1000ms! It simply gets added to the queue after 1000ms. But it’s a queue, the function has got to wait for its turn!

Now this is the part we’ve all been waiting for… Time for the event loop to do its only task: connecting the queue with the call stack! If the call stack is empty, so if all previously invoked functions have returned their values and have been popped off the stack, the first item in the queue gets added to the call stack. In this case, no other functions were invoked, meaning that the call stack was empty by the time the callback function was the first item in the queue.

The callback is added to the call stack, gets invoked, and returns a value, and gets popped off the stack.

Reading an article is fun, but you'll only get entirely comfortable with this by actually working with it over and over. Try to figure out what gets logged to the console if we run the following:

const foo = () => console.log("First");
const bar = () => setTimeout(() => console.log("Second"), 500);
const baz = () => console.log("Third");

Enter fullscreen mode Exit fullscreen mode

Got it? Let's quickly take a look at what's happening when we're running this code in a browser:

  1. We invoke bar. bar returns a setTimeout function.
  2. The callback we passed to setTimeout gets added to the Web API, the setTimeout function and bar get popped off the callstack.
  3. The timer runs, in the meantime foo gets invoked and logs First. foo returns (undefined),baz gets invoked, and the callback gets added to the queue.
  4. baz logs Third. The event loop sees the callstack is empty after baz returned, after which the callback gets added to the call stack.
  5. The callback logs Second.

Hope that this makes you feel a bit more comfortable with the event loop! Don't worry if it still seems confusing, the most important thing is to understand where certain errors/behavior can come from in order to Google the right terms efficiently and end up on the correct Stack Overflow page 💪🏼 Feel free to reach out to me if you have any questions!

Discussion (118)

logan70 profile image

Hi, Lydia Hallie, it is a great article.

Can I translate this article into Chinese to help more Chinese developers(With original author and link, of course).

lydiahallie profile image
Lydia Hallie Author


diegolepore profile image
Diego Palacios Lepore

Hi, Lydia!

This is such a great article! 😃

I was looking a clear post about this subject and yours is super comprehensive and well explained (btw, I loved the gifs). I'm planning to talk to my team about the event loop soon (in spanish).

I'm sure you might have heard about this tool that helps you play with this cycle and see in real time how it goes:

karataev profile image
Eugene Karataev

Thanks for the great article and animations!
It's interesting why "event loop" question is so common on interviews, if it's job is just to transport code blocks from the queue to the call stack. I think better question would be to ask to describe how the JS mechanism works as a whole thing with call stack, web api, queue and event loop.

rafaelbeckel profile image
Rafael Beckel

Interesting article! What did you use to animate the gifs?

lydiahallie profile image
Lydia Hallie Author

As a true professional I use keynote and screen record it lol

igmuska profile image

total de minimis production effect, the simplest way is usually the correct, least expensive way, Occam's Razor

squidbe profile image

Professional enough!

thebilson profile image

I'm also a visual learner, so this was very helpful. I'm still early on with JavaScript and it's challenging to understand it all; are there any books out there for us visual learner that you might recommend?

toanoop profile image
Anoop Sivadas

Try the book written by a John duckett

ocalde profile image
Oscar Calderon

Hi Lydia. Thanks for taking the time of generating these animations in order to explain it in a very simple way. Still, I have doubts regarding the Call Stack. Is it the same as the main thread in which JS runs? I mean, I understood that, although JS is single threaded, but for the asynchronous logic that gets executed, NodeJS would spawn threads for it while processing the main logic in the single thread. Thanks in advance :)

codefinity profile image
Manav Misra

This is a great ❓, but probably gets a bit more 'low-level' than we need to just understand the behavior of our JS code with relation to the event loop.
However, my understanding is that the JS Engine/Runtime Environment consists of only the stack and the heap. The stack is what is 🏃🏽‍♂️on that single thread. Meanwhile, that message queue is part of the asynchronous browser environment. So, JS's single thread runs through call stack on its single thread and then checks that mesage queue to see what else needs to be done on its thread when it has the chance.

avneeshroks profile image

I think in case of NodeJs, it's just the c++ Api's Insted of web/browser's Api.

sebasqui profile image

Hi @avneeshroks , I have recently cloned and run the NodeJS code and effectively C/C++ are dominant.
Remember that NodeJS is on top of the V8 engine (the one used in the Chrome browser) that Google opensourced and it is natively written in C++, running in the browser and running in a server are two different environments with different purposes and indeed different APIs. NodeJS is literally running on the same engine than Chrome, but for NodeJS it is not needed to have APIs such as those for the DOM, Window, etc as Chrome needs.

rjmunhoz profile image
Rogério Munhoz (Roz)

Awesome article! This has helped me a lot!

I was thinking about translating this series into Brazillian Portuguese. Do you happen to know if anyone has done it yet? Would you mind me doing it (ofc with links to the original series)

codajoao profile image
João Paulo

I had the same ideia. I really want to share with the team i'm part of so did you translate it or not? You found someone that did the translation of this article?

leandrorodriguesviseu profile image
Leandro Rodrigues

Great article Lydia.
Thanks so much for bring that clear explanation.

tryjude profile image

I'm not a JS developer but every now and then I have to dig into it. Over the past few years I've read lots of random things about the event loop but this is the first time I've had a clear picture of what's going on in the web browser (via the web api). Thanks!

stanleysathler profile image
Stanley Sathler

Thank you so much for the illustrations, Lydia! Very helpful, indeed!

One question: what happens when the main thread is blocked - i.e. the UI freezes? Would the whole interaction within that viewport be blocked - e.g. cursor wouldn't change after hovering a link?

I think I've never faced this situation before, so I'm curious how to identify such situation. Is there any way to simulate a huge processing in order to freeze my UI, just to see that?

Thanks in advance!

brunouyuy profile image

Hi, you can try this:

        function wait5seconds() {
            const plus5seconds = new Date().getTime() + 5000;
            while ( plus5seconds > new Date().getTime() ) {}

            console.log( 'wait5seconds end' );

        function clickHandler() {
            console.log( 'click event' );

        document.addEventListener( 'click',
            clickHandler ); // al comunicarme con la API del DOM estoy saliendo de JS 

        console.log( 'end script execution' );

Execute this script, and press a lot of clicks, the clicks events will appear at the end ( because the dom events are push into the queue.

I think that what you need to take into consideration is when you are performing a task that it might take some time, that might block the UI.

gaurangdhorda profile image

In this particular case de-bouncing is useful when we click on button..

cryptic022 profile image
Pankaj Kumar

Just write a for loop which is printing millions numbers. Call this function on any click function. You will see the effect.

miwsyed profile image
Syed Mustafa Naqvi

Hi, Lydia Hallie can you tell me what is the case with setInterval in call stack a combination of setTimeout and setInterval see the usecase below. Is setInterval also supposed to go to webAPI?

let c = 0;
let id = setInterval(()=> {

setTimeout(()=> {
// prints
/* 0
and then stops  */
Enter fullscreen mode Exit fullscreen mode
ccwukong profile image
Nick Chen

Hi Lydia, I love the series. Just wondering what tool did you use to make those animations? I'm also writing some tech stuff but I can't find a perfect virtualization tool to illustrate my ideas, but your animations really match what I was looking for.

banzy profile image

Bravo! It's a great article, exactly what I was looking for showing to my team.
Just an extra consideration, it would be very cool to show a final example when we have actually more than one async item at queue. Taking into consideration different times of response for those functions.

cncuckoo profile image
Songfeng Li(李松峰) • Edited on

Good demonstration! But a little issue exists in my opinion.

The 1st animation, when the respond() function was pushed to the call stack and executed, the setTimeout() function should be pushed into the call stack (and executed) as soon as possible, instead of waited for about 1 second. Because, as the first and only one line code inside the respond() function, the call to setTimeout( ) should be executed immediately at that time. The second argument of setTimeout(), 1000ms, has only to do with how long the timer should be waiting to add the callback to the task queue, it does not have any effect for when the setTimeout() should be pushed into the call stack.

I wish I had made this little issue clear. btw, the last animation has the same issue too. Thank you.

chanmilee profile image
Chanmi Lee

Tons of thanks for this great article and awesome animations! :)
I wonder if it would be possible to translate this article to Korean with the original post link for making this useful content be more accessible for other readers.

jonasroessum profile image
Jonas Røssum

Really nice article!
One thing I was confused about was

invoke bar. bar returns a setTimeout function.

Doesn't setTimeout return an id that you can pass to clearTimeout? 🤔

jagajastic profile image
Ibrahim Joseph M.

Yes, It does Jonas, so lets say

let id = setTimeout( () => {
return "hey"}, 1000);

console.log(id) // you will get 1

let id2 = setTimeout( () => {
return "hey"}, 1000);

console.log(id2) // you will get 2

thamerbelfkihthamer profile image
thamer belfkih

thank guys to point out this detail, in the same context what's the purpose of this Id and it is used by the web API or the call stack for some purpose? thanks in advance

adnanbabakan profile image
Adnan Babakan (he/him)

Hi Lydia
This an amazing visualization and demonstration of JavaScript event loop.

I want to ask you permission to translate this article to Persian (Iran's language) with the original post link of course so this article would be more accessible for other readers.

lydiahallie profile image
Lydia Hallie Author

Sure 😃

max_tulian profile image
Max (he/his)

Good post, I really appreciate the effort you do to explain the things :)

rishavkumar11111 profile image
Rishav Kumar

Hi, Lydia Hallie, this is a really informative article.
Please make a similar article on event loop in Node.js if possible.
It will be of immense importance to me as I am unable to get a proper explanation with an example.

escornwell profile image
Eric Cornwell

Great explanations and descriptions. Interesting to note that in the final example the timer value is unimportant. Someone who is unaware of how the queue works might be surprised to find that a timer value of 0 still logs "Second" last. Which is actually an easy way to yield to the UI during a long-running process if it can be continued via a timer callback, which will happen virtually immediately if the queue is empty.

ruizhen88 profile image

Thanks for the great article, Lydia! Do you mind if I translate this JS Visualizeed series into Korean with the original article and author credit? I think a lot of Korean developers would be interested in learning them.

arctekdev profile image
Arctek 🧊

You did a fantastic job of explaining and animating this.

hannadrehman profile image
hannad rehman

What if there are no functions is the program?.lets say i have 10 instructions like variable deceleration, assignment , arthematic operations etc. Will all these instructions also go to call stack?
Var a = 10:
Var b;
b = a+ 10;

mohamedlazybob profile image

I just wanna thank you for this amazing explanation, the first time I've read this 3 months ago, everything was new to me and blur.

Today I went on it again and it's just crystal clear too!

Thank you 3

gsvidal profile image

Amazing!, it was so helpful, thanks

kanxiaoxi profile image

Hi, Lydia Hallie, Thank you for your great work. I want to translate your articles in Chinese to improve my English and skills😊.

ashimb profile image

Fantastic visualization. Thanks Lydia

ijebusoma profile image
Vanessa Osuka

So it's safe to say the purpose of the event loop is to prevent any callback clashes? 🤔

lydiahallie profile image
Lydia Hallie Author

Hm no, not really. Imagine we have 4 tasks, and the 2nd tasks needs a delay. If this delay would've happened on the main thread, nothing would've been able to run on the thread while we were waiting:

However, the web api gives us some sort of asynchronous behavior by letting us put stuff "to the side" so to say. We can now keep on running other tasks, thus keeping an interactive UI, while tasks are running in the background:

Hope this somehow made sense haha I just woke up so my illustrations may not be optimal 😜

stanleysathler profile image
Stanley Sathler

So can we say that preventing callback clashes is the queue's job, instead of event loop's one?

devworkssimone profile image
DevWorksSimone • Edited on


avneeshroks profile image

Hey Lydia! This was amazingly explained! One thing I'm still now able to understand is what's microtasks and macrotasks! How engine prioritize those? Also how the Render/Paint queue work with the Normal queue?

evelynpei profile image
Evelyn Pei

Very helpful in further understanding the event loop! Thanks for posting, Lydia! :)