How does Javascript code execute?
In brief, Javascript is a single-threaded language, meaning it must complete execution of it’s active snippet of code prior to moving on to the next snippet of code. If that is the case, how is it possible that Javascript is able to delay execution of a snippet until a certain amount of time has passed (using the setTimeout function for example)?
The answer lies in Javascripts intimate connection with the Web API.
Stepping back a bit, what does it mean when we say Javascript is single threaded? In computer science terms, a thread is the smallest sequence of programmed instructions which can be managed by a scheduler. In layman’s terms a thread is a task which is given to the scheduler to execute.
Javascript, being single-threaded, means that it will execute tasks (in this instance, snippets of code) in the order the code is provided, reading through line by line until all code has been executed. If you’re familiar with the concept of a call stack, you can think of every javascript file as a unit on that call stack to be executed.
So what happens when you include a setTimeout function within that executable code? The answer lies in the intimate relationship between Javascript’s event queue, event loop, and the Browser API.
Call Stack, Callback Queue, and Event Loop
A Restaurant Analogy
I’m big into analogies, and this is one of the cleaner ones I can make. Imagine Javascript is a restaurant with a kitchen, a waiter, and an individual named Frank eating a large quantity of pancakes.
Each pancake represents a code snippet to execute. The stack of pancakes delivered on each plate represents the Call Stack. Frank represents the Javascript Engine executing the code snippets The kitchen represents the Browser API (sometimes called the Web API) The waiter communicates with the kitchen and Frank, representing the handoff of Browser API requests and the delivery of “cooked” pancakes, or new code to be executed.
In this world, Frank is particular in how he eats and carries four key traits in his eating habits. He only eats pancakes He will eat as many pancakes as he is served Everytime he finds a blueberry pancake, he sends it back to the kitchen to have the blueberries removed He will only eat one pancake at a time, pulling it off the top of the stack of pancakes, placing it on a separate dish, and eating it to completion.
Frank shows up to the restaurant and immediately begins consuming pancakes. On his plate he has three pancakes, he carefully takes the first one off the stack, transfers it to a new plate, finds that it is a plain pancake and consumes it. Once he finishes eating that pancake, he removes the second pancake, transfers it to a new plate, and finds that it is a blueberry pancake. Frank is distraught, he calls over the waiter and says, “I get migraines when I eat blueberry pancakes, can you please have them remove the blue berries.” The waiter dutifully takes the blueberry pancake back to the kitchen and says, “I promise we’ll make this into a plain pancake for you.”
Frank, an ever hungry man, goes to the stack of pancakes on his plate and finds the third and final pancake sitting there drenched in syrup. He takes the pancake, puts it on a new plate, finds that it is a plain pancake, and consumes it.
He then looks at his plate, and finds no pancakes there. He then asks the waiter, “was the kitchen able to fix that pancake? Is there more for me to eat?”
The waiter rushes back to the kitchen and returns carrying a new plate of pancakes for Frank, “The kitchen apologizes for the blueberry mistake, here’s a stack of pancakes on the house.”
Frank looks at the stack, and begins his consumption ritual. Pulling the top pancake off, checking to see if it has blueberries, eating it if it does not, and returning it to the kitchen if it does.
Translating the Analogy
This rough analogy explains the general flow of execution and communication between the Javascript engine and the Browser API. Javascript will execute all code snippets in the order they are received. In this instance, Frank see’s the blueberry pancake and sends it back, but he continues eating the existing pancakes on his plate. The Javascript engine performs the exact same process; whenever Javascript recognizes a function which should be executed in by the Browser API (like setTimeout) it will ‘hand off that snippet of code’ to the Browser API and will continue executing the code still on it’s plate (in the call stack).
If it runs out of code to execute in the call stack, Javascript will check the event queue for new code blocks to execute (just as Frank checked with the waiter to see if the pancakes were ready). In the case of setTimeout, if the time has elapsed on the setTimeout function, the code within that setTimeout will be added to the Event Queue ready to be executed (or the waiter will come back with a plate of pancakes for Frank to eat). Javascript will then add that code to the call stack and will begin executing it in order.
In this analogy, Frank’s constant communication with the waiter, and the waiter sprinting back and forth from Frank to the kitchen to satiate Frank’s insatiable hunger represents the overall event loop executing at all moments within Javascript.
Putting it into Practice
When I was doing a bit of research how to teach this concept, I stumbled on the following tool which neatly illustrates this concept.
If you open up the console in the Chrome Dev Tools, you'll see the order the console.logs are executed.