Intro to Asynchronous JavaScript
Tags: beginners, javascript
Published: 2021-06-20 00:53:40

Let's all be honest and address the elephant in the room. As a beginner developer, asynchronous programming is one of the hardest and confusing JavaScript concepts to grasp. 

<img src="https://64.media.tumblr.com/94ef34c03174b05e5613ec1586c349f1/tumblr_pou62wLxEI1wq5h3eo2_500.gifv" alt="confusing bruce" />
A bit out of context, but can't we agree that the async concept can be as confusing as Bruce Banner didn't know there's an Ant-Man and a Spider-Man? 😅

I struggled to learn `Promises` and `async` and `await` in the past few months, and I have seen `async` and `await` in my interviews. I decided to write a series of Async JS to break this struggle and hopefully will help anyone who is trying to understand asynchronous programming in JavaScript.

There are 4 parts in this series:
1. Intro to Asynchronous JS (this article)
2. `Promises`
3. More `Promises`
4. `async/await`


## Introduction

Before we start talking about `Promises`, `async`, `await`, we need to first understand **why do we care about handling asynchronously?** 

(Disclaimer: I understand the importance of learning how async works in both client-side and server-side. But in this article, I will mainly focus on client-side JS rather than server-side. I would like to write more about server-side in the future.)

First off, we have to understand JavaScript is always synchronous and single-threaded. In other words, when one block of code is being executed, no other block of code will be executed. 

![synchronous demonstration](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ntpmrg34mp98ub7hfmbh.gif)

As you can see from above, the console printed the values according to the order.

JavaScript programs in web browser is typically **event-driven**. In other words, JavaScript is not going to do anything until the user tap or click on something. That's the client side. As for the JS-based server side, it usually waits for client requests to arrive over internet before doing anything. 

We would use asynchronous JS in cases like fetching or accessing some kind of resource from a third party API. 

Say you have a pretty large image on top of your website from a server, if we follow the JS synchronous style, the web browser has to completely finish loading the image before loading the rest of the content. For user experience, this behavior is not ideal, because you don't know how long the image will take to load. 

If we use the `fetch` method to fetch the image from a server for the website, since `fetch` is asynchronous, when running the next line, it will throw an error as the response is not yet available (I PROMISE -- pun intended -- this will make more sense later on).

(You probably notice the images/GIFs in this article took a little bit time to load while the text is available -- a real example of asynchronous programming)

## Asynchronous Programming with Callbacks

Before we dive into `Promise` (will be introduced in the next article), the most fundamental concept we have to understand is **callbacks** (passing another function in a function and will be invoked when some condition is met or some event is occured). This is also the old-fashioned way of handling asynchronous programming before the introduction of `Promise` in ES6. But some of these callbacks are still commonly seen without `Promise`.

### Timers (`setTimeOut()`)

Using the example above from the Introduction section, a quick refresher of what we want in the following order:
1. ice cream
2. boba tea
3. iced coffee
4. beach 

What if I want boba tea after I go to beach, let's add `setTimeOut()` and get it 2 seconds (1000 milliseconds = 1 second) after I go to beach? Let's see how it looks like: 

![setTimeOut Demo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kq9fbfcqmfghd2rlb5yu.gif)

As you can see, "boba tea" appears ~2 sec after everything is printed on the console! 

The first argument of `setTimeOut()` is a callback function and the second argument is a time interval measured in milliseconds. 

There's another type of timer function called `setInterval()`. It is useful if you want a function to run repeatedly, but I will not cover in this article. Feel free to check this out <a href="https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval">here</a> for more info about `setInterval()` on MDN.

### Events

Speaking of events, you probably heard of `addEventListener()`. As mentioned in the intro, client-side JavaScript programs are almost universally event-driven. The web browser invokes these callback functions whenever a specified event occurs (as you may be familiar with hovering, clicking a mouse button, pressing a key on the keyboard). These callback functions are known as **event listener** and **event handler**. 

`addEventListener()` is the method to perform these callback functions based on specified event in a specified content. The second parameter of `addEventListener()` method is an example of async callback. 

Here is the <a href="https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_element_addeventlistener">example</a> from W3Schools:
```javascript
let btn = document.getElementById("myBtn");

// a callback function to be invoked when the user clicks on
// that button
btn.addEventListener("click", () => {
  document.getElementById("demo").innerHTML = "Hello World";
});
```

Here's what happened, when a user clicks on a button that represent the HTML `<button>` element that has an ID `myBtn`,  the text "Hello World" will show up.

![addEventListener() Demo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h7syjqj833rck7f5wdul.gif)

The callback function is not immediately executed. Once any specified event occurs (in this case is "clicking"), the callback function will be performed **asynchronously** somewhere inside the HTML body.

---

✨ Pause for this iconic MCU GIF before we get to the final callbacks ✨
<img src="https://i.pinimg.com/originals/34/4d/8f/344d8f8a98ad8b8db6359849d24d78f7.gif" alt="MCU: Last Stand" />

(I also needed to take a quick tea break here 😬)

---

### Network Events/XMLHttpRequest

Last but not least, fetching data from a web server is another common source of asynchrony in JS programming (Like the example of fetching a large image I mentioned earlier in the intro section).

We would use an API object called `XMLHttpRequest` to interact with servers. 

According to <a href="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest">MDN</a>, 
> XMLHttpRequest (XHR) objects are used to interact with servers. You can retrieve data from a URL without having to do a full page refresh. This enables a Web page to update just part of a page without disrupting what the user is doing. XMLHttpRequest is used heavily in AJAX programming.

Here's how it looks like (from [MDN](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Introducing#async_callbacks)):
```javascript
function loadData(url, type, callback) {
  let request = new XMLHttpRequest();
  request.open("GET", url);
  response.responseType = type;
  
  request.onload = function() {
   callback(request.response);
  };

  request.send();
}

function displayImg(pic) {
  let objectURL = URL.createObjectURL(pic);
 
  let image = document.createElement('img');
  image.src = objectURL;
  document.body.appendChild(image); 
}

loadData('starbucks.jpg', 'pics', displayImg);
```
Quick breakdown: 

We separate two functions: 
1. `loadData` to fetch the data from another server with `XMLHttpRequest` and `displayImg` to create an image to display the fetched data.  
2. We then take the `displayImg` as a callback function, as well as the URL and the content type. As the web browser loads the JS program, the `XMLHttpRequest` class plus the callback function would handle the server's response asynchronously and make HTTP request. 

---

I know that's a lot to learn, but understanding the fundamental of callbacks helps understanding why `Promises` was introduced. In the next article, we will look into using `Promises` to simplify asynchronous programming. 

See you in the next article!

## Resources
🌟 <a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Introducing#asynchronous_javascript">Asynchronous JavaScript</a> (MDN)
🌟 <a href="https://eloquentjavascript.net/11_async.html">Eloquent JavaScript Chapter 11: Asynchronous Programming</a>
🌟 JavaScript The Definitive Guide by David Flanagan (7th Edition) Chapter 13: Asynchronous JavaScript (Pg. 341 - 344) (<a href="https://www.amazon.com/_/dp/1491952024?tag=oreilly20-20">Amazon</a>)