You’re waiting in line. The cashier rings up a drunk undergrad’s Funyuns a few places ahead of you. But the undergrad has realized he forgot his wallet. He says he’ll be right back and runs out the door. What should happen now? There’s a line of people waiting, but the cashier has already started ringing up this guy’s order. Is he running across the street? Across town? Do we all wait for him to get back? Will he even remember to come back? If we were a synchronous function, we’d have to wait however long it takes.
One solution to the problem above might be: go to a different line. If we were at the Ruby store, or Python, or Java, or Haskell, or Elixer, this might be a manager’s solution. These are, after all, multithreaded languages. There are multiple lines to choose from.
NOTE: Languages are not primarily identified as being single threaded or multithreaded (i.e., being single-threaded or multithreaded is a property of how a language is processed rather than a “type” of language). A code-based metaphor might be to say this.isMultithreaded is a method (metaphorically; this is not literally true) rather than SingleThread or Multithread classes extending the parent class of Language.
The Call Stack
The call stack is the data structure that stores and manages the execution contexts of our script. Execution context is something like “the environment (or scope) in which a function exists and operates.” If you’re thinking about scope chain, you’re in the right neighborhood. So, the call stack keeps track of our functions and determines how/when they are executed as well as the information (variables, objects, etc.) to which a function has access.
Stacks vs. Heaps
Call stacks and memory heaps are aptly named to denote their our level of access. Heaps are not strictly organized. That’s ok though, we can grab what we need from a heap when we need it. That’s good for keeping objects and values close, where we might reference them again in no particular order. When we need more structure, like when we want to make sure things happen in a particular order, we can use a stack.
One constraint of a stack is that we only have access to the top. Imagine one of those buffet plate dispensers; you can only get to the plates at the bottom of the stack by removing the plates from the top of the stack. In programming, this is referred to as a LIFO (Last In, First Out) data processing method.
As a consequence, our code must generally proceed in order, with each function awaiting the completion of the preceding block. We can see this in action in the following block:
alert('You clicked me!');
let pElem = document.createElement('p');
pElem.textContent = 'This is a newly-added paragraph.';
Single Thread Async
It Takes a Browser