Javascript Async Await Tutorial

Elliot Forbes Elliot Forbes ⏰ 3 Minutes 📅 Mar 10, 2018

In this tutorial, we are going to have a look at how you can make your JavaScript programs more syntactically beautiful with the use of both the async and await keywords. Both of these keywords were introduced into Node in version 7.6. Hopefully, by the end of the tutorial, you will be going back to refactor all of your old NodeJS based applications to replace all of your chained callbacks and promises.

A Simple Introduction

Let us first have a look at how we would typically deal with functions that return promises without async or await. We’ll create a myPromise() function which will just return a Promise like so:

function myPromise() {
  return new Promise((resolve, reject) => {
    resolve("My Promise Response");
  });
}

Let’s now try and call the myPromise() function within a traditional function. This will mean we have to again return a Promise and only resolve this returned Promise once we have the result from our myPromise() function. Like so:

function myTraditionalFunction() {
  return new Promise((resolve, reject) => {
    myPromise().then(result => {
      resolve(result);
    });
  });
}

myTraditionalFunction().then(x => console.log(x));

Now this isn’t too bad for a simple program, but consider what happens when our programs grow in size and complexity, we’ll then have to deal with hundreds of chained promise functions and our codebase will be needlessly complex.

Let’s have a look at how we can improve this with the use of async and await. We will create a myAsyncFunction() which will be prepended by the async keyword. Within the function body, we can then get

async function myAsyncFunction() {
  var resp = await myPromise();
  return resp;
}

function myPromise() {
  return new Promise((resolve, reject) => {
    resolve("My Promise Response");
  });
}

myAsyncFunction().then(x => console.log(x));

We’ve managed to achieve the same result with our myAsyncFunction in 4 lines of code, as we had with 8 lines of code in our previous myTraditionalFunction. By utilizing the async and await keywords, we have been able to create a program that is far cleaner and more concise.

Improvements to Error Handling

Using both async and await improves the way we can deal with errors that occur inside of our promises. Let’s take for example a program that crawls a page of a website and returns the response, using traditional error handling methods we would have to write additional .catch() blocks to catch any errors that our promises may throw.

With the await keyword however, we can simply wrap our promise within a try catch like so:

const axios = require("axios");

async function crawlPage(url) {
  try {
    let result = await axios.get(url);
    console.log(result);
  } catch (err) {
    console.log(err);
  }
}

crawlPage("https://tutorialedge.net/");

This is far cleaner and simpler than using the .catch() block approach. Let’s flesh this sample out a little and create a very simple web crawler that can retrieve all of the links on a given page:

const axios = require("axios");
const cheerio = require("cheerio");

async function crawlPage(url) {
  try {
    let result = await axios.get(url);

    $ = cheerio.load(result.data);
    links = $("a");

    $(links).each((i, link) => {
      console.log(i);
      console.log($(link).attr("href"));
    });
  } catch (err) {
    console.log(err);
  }
}

crawlPage("https://tutorialedge.net/");

Conclusion

Hopefully, you found this tutorial useful and I’ve shown you the light when it comes to using async and await within your own JavaScript programs. I would love to hear your feedback so please feel free to reach out to me on twitter: @Elliot_F.