What the Hell Is: Asynchronous JavaScript

Tim Roberts
Let’s Learn:
Published in
8 min readApr 12, 2016

The first time I tried an AJAX request, I couldn’t even figure out what the documents were trying to tell me or how to configure that thing in the squiggly lines between the parentheses to make it magically show text on my screen let alone knew what the A in AJAX meant. Maybe this will help.

You can see the code we’re talking about at this codepen. You’re gonna need a browser whose dev tools pick up the `debugger` keyword. Chrome on Ubuntu seems to work fine for me.

If you’re in PHP-land, you can do something like this:

$homepage = file_get_contents(‘http://www.example.com/');
echo $homepage;

That will fetch the url and get its contents for you and on the very next line it will dump the posts onto the screen. So what happens if I want to get the content of a url in JavaScript and its single-threaded world?

var homepage = $.ajax({ url: ‘http://www.example.com/’, type: ‘GET’});
console.log(homepage);

Seems simple enough. But let’s run that in CodePen, with a real address that I know what the data is going to be. We’ll be using Babel so we can use ES6 sytanx and look cool in front of all of our friends and so we can use fetch instead of AJAX because that is what the web will be using soon so might as well get used to it now!

That’s so fetch

So, instead of us getting my sweet WordPress API data, we are getting this weird thing back called a Promise, which is an object that has PromiseStatus and PromiseValue. Does this mean that our fetch didn’t do its job? Of course not! We just never told it what to do once it was done fetching our information so let’s do that! We’re going to be chaining our functions, just like when we say ‘$(‘#id’).click(…)’, and using the awesome promise method ‘then()’. Which, in our code, will look something like:

And theeeeeennnnnn

Since we know that setting ‘response’ equal to fetch returns us a promise, I decided to make it an empty string and console.log it right after the fetch command to see what its value is. We’ll set it later to what data is equal to but for now it’s good to see what it looks like before we try to change it!

That first ‘then()’ takes an anonymous function as its argument and all that function does is return whatever ‘res.json()’ is. Since ‘res.json()’ returns ANOTHER promise, we can use ‘then()’ again to console.log whatever it is that function returns.

Whoa whoa whoa. Anonymous function? res.json()? Promises? I FEEL LIKE I’M TAKING CRAZY PILLS! Let’s take a step back and figure out what some of these words mean since they seem pretty important.

An anonymous function is just a function that doesn’t have a name assigned to it. When you put `.click(function(){…}); ` you are passing an anonymous function to the click method. Not as scary as it sounds, is it?

res.json is even easier to understand. Since we’re using ES6 syntax, we can lessen the characters needed for an anonymous function into simply the function’s argument and the return value. It is saying:

.then(function(res){
return res.json();
})

That function resolves into a new Promise so what is a Promise anyways? Well, the skinny of it is that a Promise is literally just a promise to your worker that sometime in the future this value will resolve into either a value or an error. It’s like a place holder for a value that you just aren’t sure when your worker will get around to assigning it.

Promises and anonymous functions are at the heart of asynchronous JavaScript. Since JavaScript is a single-threaded language (can only do one operation at a time), we can’t really wait for our worker to go across the internet wires, retrieve some data, and then return to us while hijacking the DOM and user experience. Don’t we all hate when our computer freezes or the page we’re visiting throws a ‘script’ error and asks us if we want to end it?

This single-threaded nature of JavaScript is getting ‘fixed’ with callbacks/asynchronous coding and Promises let us almost write in a synchronous manner. There’s alot more to Promises and callbacks than I can ever go into but funfun Functions on Youtube does a great job of explaining them and a whole lot more. Seriously, you need to check that guy out. He is my spirit animal.

We all caught up on? No? Watch the guy’s videos. Seriously.

Back to our code. If you haven’t ran that code yet, try to imagine in which order the console.log’s will be executed. If you guessed that console.log(response) will execute first, you’re a smart cookie. But now, let’s try assigning a value to response from within the last .then() block where we have data being console.log’d so instead of `console.log(data);` let’s have it say `response = data;`. Now when we run this, what will be consoled out?

Still an empty string?! What?! We just told our worker “Hey, when you get the value and make it into JSON, I want you to assign it to the box labeled response!” Why has he forsaken us so?!

If you remember from being so smart in the last step, console.log(response) fires long before the last .then() block is even looked at by the computer. To see this, we can start adding `debugger;` in our code and see what our computer is actually doing.

It’s not a bug, it’s a feature!

We just add `debugger;` on the lines of code that we want our worker to stop and let us step into her world for a moment. This works in Chrome but I am not sure how it fares in other browsers. Now, if we have the dev tools console open and run this code, it should stop and let us look around.

Maybe we can zoom in?

As you can see, right before our worker gets to the fetch command, he thinks that response is equal to ` ‘ ‘ `, which he should. If we press the golden arrow in the console underneath Security, we can step until our worker sees the next `debugger;` command. Which line will we stop on next?

WHAAAT?!

Okay, that’s weird. It jumped 7 lines of code, somehow missing our debugger inside of the second `.then()` function and is now almost to the end of our program! If we hover over each `response`, we will see that it is still equal to ` ‘ ‘ ` so it appears as if our worker hasn’t even looked at our second `then()` statement. What gives?! Let’s press that orange play button again and see.

It somehow jumps UP the code, with the only instruction we gave it after the debugger was the console.log response. That’s hella weird. But now, let’s hover over each `response` and see what it is equal to. Uh. Still an empty string. Now actually that is weird….

Oh. Right. Duh. Our debugger statement is BEFORE the assignment. I bet you if we moved it after, all of that would change…

WE ALL MAKE MISTAKES. GOSH!

So, we moved our debugger statement to be after the response = data statement. Now let’s click that play button until we reach it and hover over `response` everywhere it’s in the code to see what it is set to at that moment in time. Yup, okay, empty string. And yup, okay, still all of them are empty strings. And third time’s the char-WHAT THE ACTUAL HELL?

Everything is changed. Not only did assigning our `data` value to `response` make it a whole new object full of awesome json data but it also changed what it equals outside of this function. Hover over each `response` and see for yourself.

Well, of course, you might be saying. Scope this and encapsulation that. So let’s add a function that will run in one second’s time (maybe perhaps to mimic a future action by the user…?) like so:

Just telling our computer “hey, in 1000 milliseconds, I want you to run this function.

Run and let’s step through. Like always, the first two times we can check `response`, we end up with an empty string. The third time, inside of the last .then() block, we see that it is now available for the whole script as an actual value. But what about inside of the future function? Do we have data?

This time, it appears as if we do. But perhaps this request takes a long time or the user asks for the information much quicker than 1s (or the very next line in our code asks for the value or response in order to massage the data). What in the world are we to do then? (see what I did there?)

That’s for a future episode. Spend some time messing around with `fetch` and Promises and the debugger console. Get to know what the hell your worker is doing the only way I know how: stepping into her shoes and checking out the environment. This post is parse on ‘best practice’ or how to work with async code and it’s supposed to be.

For me at least, this idea of asynchronous code made sense when the response times were milliseconds but as my applications have grown larger and the logic more convoluted, just trying to figure out when a value will actually have a value and be able to be worked on becomes harder and harder to reason about in the ethereal and can only be understood by breaking it down into its simple parts as our codepen does.

Have some questions about async JavaScript? See an error (besides the damn double ` ;; ` after the then….)? Let me know! Either drop me a line at my email (timi@knoxweb.com) or respond below! Until next time!

--

--

Tim Roberts
Let’s Learn:

dev kid who likes to write in english instead of code