Say It With Me: Javascript is ASYNCHRONOUS!!
Cory Parrish
Engineer | "swiss-army-knife" bringing visions to life with leadership & code | Scalable Architecture | High Performing Teams | Humble, Hungry, Smart | Leading With Permission
Before we dive in, I just wanted to say that I decided to have a little fun with this article and hopefully bring a smile to your face. The tone I’m using is meant to be lighthearted and humorous, not to insult or offend anyone. So, let’s enjoy a few laughs together as we explore this topic!
After 15 years of interviewing engineers, you start to notice a few trends. For the longest time, everyone knew that JavaScript was an asynchronous language—one of those basic facts you could count on, like gravity, the sun rising in the east, or a new version of Internet Explorer ripping your soul out. You can trust me, I know now a thing or two about taking souls!
Yes, that was a ginger joke.
But then, around 2015, something changed. I thought I was tossing a layup question in interviews, only to find myself plunged into an hour-long existential crisis, explaining why lines of code weren’t executing in order. But I digress—we’ll circle back to that in a bit.
Honestly, I’m convinced there’s an evil plot at play. Someone out there, a mad genius of the highest order, has managed to bamboozle an entire generation of engineers. And right now, they’re probably sitting on their couch, cackling like a certain animated villain with a penchant for stealing the moon.
Oooohhh.... The Plot Thickens
The controversy. Oh, the things I would hear…
1. "Nuh uh, because look at my hello world code. It executes synchronously"
Oof… my head is starting to hurt. Just a twinge, but it’s there.
Ok, sure. This very contrived example executed "synchronously" because it only used one pass of the event loop. Buuutttt......
2. "Nuh uh, it’s synchronous unless I use async/await."
I can feel my brain expanding in uncomfortable ways.
You know, this is one of my favorites actually, because it gives me a chance to wax nostalgic. I get to talk about the good ol’ days of nested callback hell, variable hoisting, and enjoying not having types in my JS without boundless persecution. I could enjoy the simplicity of Backbone.js because I know basic design patterns.
Shut up, I'm not a boomer; you're a boomer.
Nowadays, when engineers use the phrase IFFE, they are talking about my decision to wear ankle socks. Leave me alone, okay! My ankles are hot.
But let's get back to the point. async/await generates a promise. It was created to give the allusion of synchronicity so we could use a more common style of programming. I mean, have you tried using a try/catch around all of those promises? Huh? Huh?
Before async/await, we used promises directly. Promises were created to handle asynchronous actions in JS using a simpler syntax that allowed us to chain asynchronous events together. Prior to this, there were only callbacks. Now this was super fun! You would often see JS code with 5+ nested callback functions and an angry Java engineer forced to write Javascript muttering to themselves about Single Responsibility and how properly named functions document your code for free ... [expletive deleted].
The point being, async/await is mirage. It is a facade sitting on top of the event loop like your classes sitting on top of the prototype chain. Now I know that sounded mean, but for the record, that was NOT an insult. Your JS classes are legitimately just a facade for the prototype chain.
3. "Nuh uh, the event loop processes things synchronously, so it is synchronous."
At this point, the only way to release the pressure building in my skull is to slam my head into something. Please, someone, help me!
Wait a second… so you know about the event loop? But… umm… why is there an event loop? How does that lead to… uh oh.... 3 + 2 equals… umm… carry the 12… is something burning?
It's OK, Let's Talk About It
Let’s break it down literally. In some programming languages, the code is executed exactly as you see it on the screen, line by line, in a specific sequence. For example, line 10 will always run before line 11, and so on. In a single thread, it’s impossible for line 20 to execute before line 10—it just doesn’t work that way. The code runs in order, or to put it another way… WAIT FOR IT… synchronously.
Javascript, on the other hand, does not always execute the code line by line. It executes the code out of sequence, or asynchronously.
Let's look at what happens with a simple HTTP call using a callback.
1. HttpProxy.get('https://www.microsoft.com'/sorry/for/ripping/ie, (response) => {
2. console.log(response.data);
3. });
4. console.log('I am done');
For a more in-depth understanding of the event loop, numerous detailed resources are available. However, we’ll intentionally skip over some finer details here.
In this scenario, we have two passes of the event loop. The first pass will initiate the HTTP request, and the second will execute our callback. Behind the scenes, Node.js handles the actual HTTP request, waits for its completion, and then triggers the callback. In many cases, the HTTP request is executed on a different thread.
Yes, Node.js is often described as "single-threaded." However, this means that as an engineer, I have direct access to the single thread that runs the event loop. Node.js itself can, and does, utilize multiple threads.
Once the HTTP request completes, the callback with the response is placed in the event queue and executed when it reaches the front of the queue.
This example illustrates how our code is executed asynchronously. Not only is the code executed out of order, but it leverages the event loop to do so. The presence of the event loop, executing events when they are ready, is evidence that JavaScript is asynchronous. While Node.js processes the events in the queue in order, or synchronously, the existence of the event queue itself defines its asynchronous nature.
Yes, you can write a simple "Hello World" program without any asynchronous calls, but that doesn’t mean the event loop ceases to exist. JavaScript remains an asynchronous language because the event loop is always present, even if it’s only making one pass to execute your code.
Async/Await is a newer syntax for managing asynchronous operations, but its usage (or absence) doesn’t determine whether the language itself is asynchronous.
So There We Have It
I’m always up for talking shop—whether it’s about tech, startups, leadership, or anything else that sparks a good conversation. If you’d like to connect, discuss something I’ve mentioned, or just network, don’t hesitate to reach out!
Happy coding!
Principal Solutions Architect at Launch Consulting
7 个月Hey Cory, always fun to hear your JS insight ??One thing, in your callback example did you mean to mention that the "console.log('I am done')" will be out of order?