The Mysterious Javascript Event Loop

Yesterday I learned something quite interesting from watching Philip Roberts talk at JSConf EU a couple of years back. Philip explained the magic that lies behind the event loop in Javascript, and why it’s so important to keep in mind when you want to build a fast & fluid app that users love.

The Call Stack

Let’s back-track a bit first. I’m still very much a newcomer to the world of Javascript, but what I do understand is that — like all programming languages — Javascript code is read from top to bottom.

Not an earth-shattering revelation by any means.

What I didn’t understand until yesterday, is that the browser has what it’s called a “call stack.” A call stack is basically an order in which it executes each piece of code (e.g. like a function). For example, here is a screenshot of Philip’s presentation where he shows how 3 functions are placed on top of one another in the call stack as the code is being executed.

The Call Stack (screenshot from Philip Robert’s presentation)

Once the top block’s code has ran, it clears off the top of the stack — and the browser moves on to the next piece of code. This is known as “synchronous” code. In other words, things in the bottom of the call stack CANNOT run until the previous block of code above them has been cleared.

While trying to understand this concept a bit better, I came across this fantastic article by Tom Coleman at Discover Meteor where he compares Javascript to your very own personal butler (by the clever name of Javes). Now, while Javes is incredibly efficient, he can only do ONE thing at a time. So in other words, if he is making you a sandwich, he can’t be be driving to the store to get you more caviar at the same time. He can only do that once he is done making you a sandwich.

The Problem

Doing basic functions that execute quickly is not a problem. But as we start building larger applications that are much more resource intensive, you can see why this becomes a problem.

For example, Javes can go and get you a beer from the fridge in a few seconds without problems (well, more like milliseconds). But what happens when you give him more complicated tasks that take a while to complete?

His to-do list starts growing and things that need to get done start NOT getting done. No bueno, Javes.

For example, Tom gives us a great example: What if Javes needs to go the post office and send a package to a person, and this person will be sending Javes something back for us? Do we want Javes to stay at the post office and wait until he gets the package days from now?

Of course not! The car needs to be washed, the house needs to be cleaned, and your back isn’t going to wash itself.

But before I get too carried away with my dreams of having a personal butler, here are some real-world problems that this can cause in website and web applications:

  • Unresponsive user interfaces (you can’t click on anything else until the call stack clears)
  • Lagging browser speeds (commonly seen with misuse of animations)
  • Poor performing code that could lead to scalability issues

Asynchronous Functions

That is when asynchronous functions and the event loop come the rescue. Contrary to sync functions, async functions allow the browser to process things MUCH more efficiently.

So, in the case of our dear butler Javes, if he had to run to the post office, that’d no longer be a problem. He’d simply go, drop off a package, write down exactly WHEN the package will come back, and then return home to move on to his next task. That way he is staying as efficient as possible.

And when it’s time to go pick-up the package he’s been sent back, he simply puts it on his to-do list for the day and gets it done.

The event loop is the magic that powers this process in Javascript.

When an asynchronous function is called and it takes a while to return with something (i.e. like data from another website), this gets pushed to a special “task queue” (aka Javes’ Pending Items List). In the meantime, the rest of the code can keep running efficiently in the main call stack.

Once everything in the call stack clears, your event loop is the responsible party that brings in that “callback” function into the current call stack to get executed.

Magic, isn’t it?

Conclusion

No, I haven’t fully understood everything about Javascript yet. Not by a long shot.

But this event loop concept makes a lot of sense and I think it’s important for all of us developers to understand and keep in mind when building web apps that are fast, responsive, and a joy for people to use everyday.