How Does JavaScript Do Async?

Part One: The Call Stack, JavaScript Engines, and Web APIs

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.

In Sync

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.

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.

alert('You clicked me!');
let pElem = document.createElement('p');
pElem.textContent = 'This is a newly-added paragraph.';
document.body.appendChild(pElem);
/* source: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Introducing */

Blocking Functions

Javascript will evaluate code line by line. So, when it hits the first line — the alert() — a message will appear. Now, the rest of our code must await the completion of the alert. This is an example of a blocking function. Until the function is completed (we’ve clicked “OK”), we can’t see our newly-added paragraph, or interact with anything else that might be on our page.

Single Thread Async

So we’re dealing with the web. We probably need to get information from other servers and we don’t know how long that’s going to take (returning to the bodega metaphor, we don’t know how long the undergrad will take to get back). We don’t want the line to be held up indefinitely. Thus enters asynchronous Javascript, allowing us to metaphorically skip the line and do more work while we wait.

It Takes a Browser

For JavaScript to behave asynchronously, it needs some things that only the browser (or Node.js) can offer. Namely, JavaScript engines and Web APIs.

Full Stack Web Developer//MFA in Creative Nonfiction

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store