JavaScript ES 2017: Learn Async/Await by Example

Async/Await explained through a clear example.

Brandon Morelli
codeburst

--

Udemy Black Friday Sale — Thousands of Web Development & Software Development courses are on sale for only $10 for a limited time! Full details and course recommendations can be found here.

Prerequisites

ES 2017 introduced Asynchronous functions. Async functions are essentially a cleaner way to work with asynchronous code in JavaScript. In order to understand exactly what these are, and how they work, we first need to understand Promises.

If you don’t know what Promises are, you should read this article I published on Promises before proceeding. You will not understand Async/Await in JavaScript until you understand Promises.

What is Async/Await?

  • The newest way to write asynchronous code in JavaScript.
  • It is non blocking (just like promises and callbacks).
  • Async/Await was created to simplify the process of working with and writing chained promises.
  • Async functions return a Promise. If the function throws an error, the Promise will be rejected. If the function returns a value, the Promise will be resolved.

Syntax

Writing an async function is quite simple. You just need to add the async keyword prior to function:

// Normal Functionfunction add(x,y){
return x + y;
}
// Async Functionasync function add(x,y){
return x + y;
}

Await

Async functions can make use of the await expression. This will pause the async function and wait for the Promise to resolve prior to moving on.

Example Time

Enough talk. To understand what all of this means, lets look at an example! First we’re going to create some code using promises. Once we’ve got something working, we’ll rewrite our function using async/await so you can see just how much simpler it is!

If you’re using Google Chrome, be sure to follow along by typing in the code into your developer console. You can open the console by pressing Ctrl+Shift+J (Windows / Linux) or Cmd+Opt+J (Mac).

Consider the below code:

function doubleAfter2Seconds(x) {
return new Promise(resolve => {
setTimeout(() => {
resolve(x * 2);
}, 2000);
});
}

In this code we have a function called doubleAfter2Seconds. This function will take a number as input and will resolve two seconds later with the number doubled.

We can invoke our function and pass in the number 10 to try it out. To do this, we’ll call our function while passing in 10. Then, after the promise has resolved, we’ll take our returned value and log it to the console. Here’s what this would look like:

doubleAfter2Seconds(10).then((r) => {
console.log(r);
});

Awesome!

But what if we want to run a few different values through our function and add the result? Unfortunately, we cant just add our invocations together and log them:

let sum =   doubleAfter2Seconds(10)
+ doubleAfter2Seconds(20)
+ doubleAfter2Seconds(30);
console.log(sum);
// undefined

The problem with the above code is it doesn’t actually wait for our promises to resolve before logging to the console.

One possible solution is to set up a promise chain. To do this we’ll create a new function called addPromise. Our function will take an input value, and will return a Promise. Here’s what the boilerplate code looks like:

function addPromise(x){
return new Promise(resolve => {
// Code goes here...
// resolve()
});
}

Awesome. Now we can add in our calls to our doubleAfter2Seconds function. Once we’re done, we can resolve with our new sum. In this example we should be returning x + 2*a + 2*b + 2*c. Here’s the code:

function addPromise(x){
return new Promise(resolve => {
doubleAfter2Seconds(10).then((a) => {
doubleAfter2Seconds(20).then((b) => {
doubleAfter2Seconds(30).then((c) => {
resolve(x + a + b + c);
})
})
})
});
}

Lets walk through the code again, line by line.

  • First, we create our function addPromise. This function accepts one parameter.
  • Next, we create our new Promise that we’ll be returning. Note that for the sake of simplicity, we’re not handling rejections/errors.
  • Next we invoke doubleAfter2Seconds for the first time, passing in a value of 10. Two seconds later, the return value of 20 will be returned to the a variable.
  • We invoke doubleAfter2Seconds again, this time passing in a value of 20. Two seconds later, the return value of 40 will be returned to the b variable.
  • We invoke doubleAfter2Seconds one final time, this time passing in a value of 30. Two seconds later, the return value of 60 will be returned to the c variable.
  • Finally, we resolve our Promise with the value of 10 + 20 + 40 + 60 or 130.

When we put all of the code together, here’s what it looks like:

Switching from Promises to Async/Await.

Awesome! Now lets see just how much easier we could write the above code with Async/Await!

Remove the addPromise function, and create a new function named addAsync. This function will have the exact same purpose as our addPromise did. When you create your addPromise function, make use of the async keyword. Here’s what that looks like:

async function addAsync(x) {  // code here...}

Now that you’ve created an async function, we can make use of the await keyword which will pause our code until the Promise has resolved. Here’s how easy that is:

async function addAsync(x) {
const a = await doubleAfter2Seconds(10);
const b = await doubleAfter2Seconds(20);
const c = await doubleAfter2Seconds(30);
return x + a + b + c;
}

And here’s the full code:

As you can see, we’re still making use of the same doubleAfter2Seconds function. Similarly, we’ll be invoking our addAsync() function and passing in the value of 10. Upon completion, we log the resulting value. Let’s walk through this step-by-step:

  • First we call addAsync(10) passing in the value of 10.
  • Next, we get the value of a on line 10. Since the await keyword is used, our function pauses for two seconds while we wait for the promise to resolve. Once the promise resolves, a = 20.
const a = await doubleAfter2Seconds(10);
  • Next, we get the value of b on line 11. Since the await keyword is used, our function pauses for two seconds while we wait for the promise to resolve. Once the promise resolves, b = 40.
const b = await doubleAfter2Seconds(20);
  • Next, we get the value of c on line 12. Since the await keyword is used, our function pauses for two seconds while we wait for the promise to resolve. Once the promise resolves, c = 60.
const c = await doubleAfter2Seconds(30);
  • Finally, we can return the value of x + a + b + c. Since we passed in 10 as our single parameter, we are returning the value of 10 + 20 + 40 + 60.
  • A full six seconds later, our console.log(sum)is finally run. The value of 10 + 20 + 40 + 60 is passed in, and 130 is logged to the console.

And that’s it! You’ve just created an asynchronous function in JavaScript!

As you can see, since Async functions return a Promise, they can be used interchangeably with Promises very easily. Our code is also so much cleaner and easier to read when we use Async/Await instead of long Promise chain.

Closing Notes:

Thanks for reading, and hopefully this was helpful. There is much more to Async/Await — including error handling — that we didn’t cover in this article.

If you’re still having trouble understanding what Async/Await is, it’s probably because you don’t fully understand how Promises work. Promises are key to understanding this topic. Additional information can be found on Promises here, here, and here.

If you’re ready to finally learn Web Development, check out The Ultimate Guide to Learning Full Stack Web Development in 6 months.

I publish 4 articles on web development each week. Please consider entering your email here if you’d like to be added to my once-weekly email list, or follow me on Twitter.

If this post was helpful, please click the clap 👏button below a few times to show your support! ⬇⬇

--

--

Creator of @codeburstio — Frequently posting web development tutorials & articles. Follow me on Twitter too: @BrandonMorelli