The Path to Conquering Async JavaScript
Tags: async, javascript, beginners, node
Published: 2017-10-18 00:28:43

---
title: The Path to Conquering Async JavaScript
published: true
description: A detailed path to conquering asynchronous calls in JavaScript using callbacks, promises, and await/async.
tags: async, javascript, beginners, node
---

Yoooo, I'm glad you're here! We'll be discussing how to conquer asynchronous JavaScript! As I've been trying to teach myself Node.js and build some things, I've found that async calls aren't the most trivial to learn to deal with. Async JavaScript actually takes a good amount of thought to fully comprehend. I hope to pave a path that makes understanding how to deal with async calls faster and easier.

You can find all of the code used in this article on [GitHub](https://github.com/henness17/SweetCode/tree/master/005-The-Path-to-Conquering-Asynchronous-JavaScript).

---
# What's the Problem?

JavaScript is a synchronous language, which means it is single-threaded, so it only runs one block of code at a time. A problem occurs when we want to make some sort of async call, which is a multi-threaded. The problem is that when our JavaScript calls an async function - our JavaScript continues to run, although there is a block of code running somewhere else. I run into this problem the most when I am dealing with API requests.

Here's an example -
1. The JavaScript block starts
2. An API request is made
3. JavaScript code continues AND the API request processes
4. JavaScript uses the request's response before the response is returned

![AsyncReq](https://thepracticaldev.s3.amazonaws.com/i/dxz7mmpnpz1e9ij6soe0.png)

Notice how there are two number threes? That's the problem. The JavaScript code continues to run as the request is being made. This means it's possible for the JavaScript to attempt to use the request's response value before it's available, and we take the L.

---
# The Goal
The goal is to be able to call async functions in a synchronous fashion - the calls should wait for the one before it to finish before executing:

![TheGoal](https://thepracticaldev.s3.amazonaws.com/i/6zuuyic6jeit3kwzk99c.png)

Which will look something like this when there are multiple async calls:

```javascript
var a = await asyncToGetA();
var b = await asyncToGetB(a);
alert(b);
```
---
# Using Callbacks

### What's a Callback?
So how do we overcome this issue? Well, let's first take a look at callback functions so that we can get a glance at a potential fix. Callbacks are a way of telling the code to run a function *after* another function is finished, if your code isn't making too many async calls then this is an ok option to use. This is achieved by passing a function into another function as an argument, and then calling the argument function at the end of the one it's passed to. 

Let's say we have a function, `runThisFirst()`, that we want to run before another function, `runThisSecond()`. `runThisFirst()` will simulate an async call with `setTimeout()` and set `x` to 5. Once that's finished, `runThisSecond()` will run. Since we want `runThisSecond()` to run *after* `runThisFirst()`, we are going to pass it as the callback function:

```javascript
// Define functions
var runThisFirst = function(callback){
    setTimeout(function(){ 
        x = 5;
        callback(); // runThisSecond is called
    }, 3000);
}

var runThisSecond = function(){
    alert(x);
}

// Run functions, pass runThisSecond as the callback argument 
var x;
runThisFirst(runThisSecond);
```
>You can run this code snippet on [JSFiddle](https://jsfiddle.net/jwt4y15w/).

### Callback Chaining
If callbacks fix our async issue, then can't we just chain callbacks together? You can, but it gets scary. There's this concept of [Callback Hell](http://callbackhell.com/) where the callback JavaScript code turns into a pyramid shape, making it messy and hard to understand. 

Here's a minimalist [example](https://codereview.stackexchange.com/questions/146095/example-of-callback-hell) of what the skeleton of a Callback Hell pyramid looks like:

```javascript
function one() {
  setTimeout(function() {
    console.log('1. First thing setting up second thing');
    setTimeout(function() {
      console.log('2. Second thing setting up third thing');
      setTimeout(function() {
        console.log('3. Third thing setting up fourth thing');
        setTimeout(function() {
          console.log('4. Fourth thing');
        }, 2000);
      }, 2000);
    }, 2000);
  }, 2000);
};
```

One of the best programming practices is writing readable code, and callbacks can stray us away from that when chaining too much. To avoid this, we're going to look into Promises and Async/Await.

---
# Promises

A `promise` function is a function that *promises* to return a value. This allows you to associate code with async calls, all by having the async calls be apart of the Promise. This is where we can make our API calls. :) Here's how they work:

```javascript
var somePromise = new Promise((resolve, reject) => {
  var x = 5;
  // Now wait a bit for an "async" call
  setTimeout(function(){
    resolve(x); // Return your promise!
  }, 3000);
});
```
You can see the `Promise` constructor has two parameters: `resolve`, and `reject`. If everything within the Promise goes  according to plan (there are no errors), `resolve` is called, which returns some value for the Promise. If an error occurs, the Promise should call `reject` and return the error. For this example, `reject` is not being called.

Now, let's try to run something that depends on this Promise to see if it waits for the `x` value to be resolved before executing. We can do this by using the `.then` function:

```javascript
var somePromise = new Promise((resolve, reject) => {
  var x = 5;
  // Now wait a bit for an "async" call
  setTimeout(function(){
    resolve(x); // Return your promise!
  }, 3000);
});

somePromise.then((somePromisesReturnValue) => {
  alert("Check it out: " + somePromisesReturnValue);
});
```
>You can run this code snippet on [JSFiddle](https://jsfiddle.net/nozqegb3/).

Check it out! Things are already looking cleaner and easier to understand. Nice job. :) But now, what if one Promise depends on another Promise? We'll have to chain Promises together.

In order to pass values from one Promise to another, we are going to wrap the Promise within a function like so:

```javascript
function somePromise() {
  var promise = new Promise((resolve, reject) => {
    var x = 5;
    // Now wait a bit for an "async" call
    setTimeout(function() {
      resolve(x); // Return your promise!
    }, 3000);
  });
  return promise;
}
```

### Promise Chaining
Now we can write another Promise, `anotherPromise()`, which is going to take the return value of `somePromise()` and add 1 to it. This function is going to have a shorter `setTimeout()`, so we can tell that it waits for `somePromise()` to resolve before running. Notice how we pass `somePromisesReturnValue` as an argument:

```javascript
function anotherPromise(somePromisesReturnValue) {
  var promise = new Promise((resolve, reject) => {
    var y = somePromisesReturnValue + 1; // 6
    // Now wait a bit for an "async" call
    setTimeout(function() {
      alert("Resolving: " + y);
      resolve(y); // Return your promise!
    }, 1000);
  });
  return promise;
}
```
Now, all we have to do is use the `.then` function in order to call these Promises synchronously:

```javascript
function somePromise() {
  var promise = new Promise((resolve, reject) => {
    var x = 5;
    // Now wait a bit for an "async" call
    setTimeout(function() {
      resolve(x); // Return your promise!
    }, 3000);
  });
  return promise;
}

function anotherPromise(somePromisesReturnValue) {
  var promise = new Promise((resolve, reject) => {
    var y = somePromisesReturnValue + 1; // 6
    // Now wait a bit for an "async" call
    setTimeout(function() {
      alert("Resolving: " + y);
      resolve(y); // Return your promise!
    }, 1000);
  });
  return promise;
}

somePromise().then(anotherPromise); 
```

>You can run this code snippet on [JSFiddle](https://jsfiddle.net/ycc8qLpt/).

Heck yeah! You can see that `anotherPromise()` waited for `somePromise()`'s return value, 5, before it executed its code. Things are really looking up. :)

---
# Async/Await

Awesome! So we're done, right? Nope, but we're close! If we take our code from the last section, and try to assign the return value from the Promise chain, we can see that the rest of the code isn't waiting for the entire Promise chain to resolve. "[object Promise]" is alerted first.

```javascript
function somePromise() {
  var promise = new Promise((resolve, reject) => {
    var x = 5;
    // Now wait a bit for an "async" call
    setTimeout(function() {
      resolve(x); // Return your promise!
    }, 3000);
  });
  return promise;
}

function anotherPromise(somePromisesReturnValue) {
  var promise = new Promise((resolve, reject) => {
    var y = somePromisesReturnValue + 1; // 6
    // Now wait a bit for an "async" call
    setTimeout(function() {
      alert("Resolving: " + y);
      resolve(y); // Return your promise!
    }, 1000);
  });
  return promise;
}

var chainValue = somePromise().then(anotherPromise);
alert(chainValue); // This is executing before chainValue is resolved
```

>You can run this code snippet on [JSFiddle](https://jsfiddle.net/v88qen55/).

How do we make the rest of the code wait?! That's where `async` and `await` come in. The `async` function declaration defines an async function, a function that can make async calls. The `await` operator is used to wait for a Promise to resolve, it can only be used inside an `async` function.

### Mission Accomplished
Instead of using `.then`, let's create a `main()` function so that we can make calls like the goal we had at the beginning of the article:

```javascript
function somePromise() {
  var promise = new Promise((resolve, reject) => {
    var x = 5;
    // Now wait a bit for an "async" call
    setTimeout(function() {
      resolve(x); // Return your promise!
    }, 3000);
  });
  return promise;
}

function anotherPromise(somePromisesReturnValue) {
  var promise = new Promise((resolve, reject) => {
    var y = somePromisesReturnValue + 1; // 6
    // Now wait a bit for an "async" call
    setTimeout(function() {
      resolve(y); // Return your promise!
    }, 1000);
  });
  return promise;
}

const main = async () => {
  var a = await somePromise();
  var b = await anotherPromise(a);
  alert(b);
}
main();
```
>You can run this code snippet on [JSFiddle](https://jsfiddle.net/54kug9Lz/1/).

Look how pretty that main function is :') beautiful. And there you have it, a nice looking main function that isn't a pyramid. Congratulations!

---
# Adding Broad Error Handling
You may want to add some error handling within your Promises themselves while using the `reject` callback, but you can also add overall error handling with a *try/catch* inside of the `main()` function that will catch any errors thrown throughout all of the code used within the `main()` function:

```javascript
const main = async () => {
  try{
    var a = await somePromise();
    var b = await anotherPromise(a);
    alert(b);
  }
  catch(err){
    alert('Oh no! Something went wrong! ERROR: ' + err);
  }
}
```

We can check this by throwing an error within our `anotherPromise()`:
```javascript
function somePromise() {
  var promise = new Promise((resolve, reject) => {
    var x = 5;
    // Now wait a bit for an "async" call
    setTimeout(function() {
      resolve(x); // Return your promise!
    }, 3000);
  });
  return promise;
}

function anotherPromise(somePromisesReturnValue) {
  var promise = new Promise((resolve, reject) => {
    var y = somePromisesReturnValue + 1; // 6
    throw 3292; // ERROR CODE BEING THROWN HERE
    setTimeout(function() {
      resolve(y);
    }, 1000);
  });
  return promise;
}

const main = async () => {
  try{
    var a = await somePromise();
    var b = await anotherPromise(a);
    alert(b);
  }
  catch(err){
    alert('Oh no! Something went wrong! ERROR: ' + err);
  }
}
main();
```
>You can run this code snippet on [JSFiddle](https://jsfiddle.net/sn7wLzb4/1/).

---
# Review

I'm glad that we were able to make it this far and come up with a pretty basic path for overcoming JavaScript async problems! We took a look at fixing async issues with callbacks, which can work if there isn't too much complexity. Then we dove into solving the problem with combining Promises and Async/Await! Finally, we talked about how to broadly handle errors. If you would like to learn more about error handling with Promises and Async/Await, I suggest you check out some documentation: [Promise.prototype.catch()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch) and [await](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await). 
If you'd like to work on something where this async functionality could be useful, think about checking out my article on how to [make a Twitter bot with Node.js](https://dev.to/ryhenness/nodejs-twitter-bot-bogus-definition-dmm). :)