The Call Stack, Web APIs, and Event Loop
If code is considered synchronous, then the code runs just as it reads: top-to-bottom. Everything happens in the same order, one after the other. Asynchronous, on the other hand, means that the code is able to run concurrently.
Well, then? How does it work?
Before we can dig into that, we need a solid understanding of what the call stack (commonly referred to as the stack) is, and what it does for us.
The call stack
Let’s take a look at a few simple examples, and work our way up incrementally.
We expect that when the function is called with
sayHello('Kobe');, we’ll see
printUserAge(30). When this code runs, it appears to happen instantaneously. We’ll see both results (
Hi Kobe and
The user is 30 years old) print to the console right away, one after the other. But something more is happening behind the scenes.
With functional programming, you can think of the stack like a pile, or stack of books or movies (we’ll get further into that later). However with simple, independent functions like these, it’s more akin to sliding a disc into your BluRay player. You can only play one disc at a time, and need to take the disc out before you can add another.
watchMovie() function is called three times, each time with a different argument to let us know which movie we should watch next. When the function is called, it is added to the stack, executed, then removed from the stack. Only when the function is removed from the stack will the execution continue from
watchMovie('A New Hope') on to
watchMovie('The Empire Strikes Back'). Throughout the above code, the call stack’s size does not exceed one.
The output we’d see in the console would look like this:
Watch A New Hope next!
Watch The Empire Strikes Back next!
Watch Return of the Jedi next!
watchMovie('The Empire Strike Back) once the code preceding it,
watchMovie('A New Hope'), has completed.
Let’s take a look at a few more functions. This time, we’ll cause the stack to pile up a bit.
printSquare(4)is called, and it’s added to the call stack.
square(n)function is called. It’s added onto the top of the stack too.
- Within the
multiply(n, n)is called, and added onto the top of the stack.
At the moment, the call stack would look a bit like this:
Before we can actually run
printSquare(4), we need to work our way through the stack, from top to bottom. It first returns
multiply(n, n), then
16 is finally printed to the console.
Within reason, there’s nothing wrong with piling things up on the stack. It can hold just about anything you can throw at it. That said, it is possible to exceed the stack’s limit; what’s often called a stack overflow, or blowing the stack. When it happens, you’ll see an error message along the lines of
Maximum call stack size exceeded—something that you probably came across once or twice while getting familiar with loops.
Web APIs, the callback queue, and event loop
The DOM, XMLHttpRequest, and setTimeout are examples of Web APIs
But wait, before we get too far in, why does this even matter? When would we need something to be asynchronous anyways?
So when does the code actually run? When does it get to jump onto the call stack and execute?
Not until the stack is clear.
All of your program’s synchronous code will hop on and off the call stack, while passing any async operations to the Web APIs, and callback queue. Finally, when the call stack is clear, and all synchronous code has been executed, the event loop begins passing the actions from the callback queue onto the stack, allowing each action to execute completely before passing the next onto the stack. When the current async operation clears from the stack, the event loop adds the next action from the callback queue onto the stack. This pattern continues to repeat until the stack and callback queue are both empty.
- What the heck is the event loop anyway? — YouTube: Philip Roberts | JSConf EU
- MDN: Concurrency model and the event loop — MDN’s take on how async works behind the scenes
- MDN: Web APIs — Learn about all the Web APIs available
- Visualize your own code in the event loop with Loupe — An interactive event loop visualization by Philip Roberts