Skip to content
Hou - Engineer & Tech Educator

Learn Modern JavaScript - Async Programming with `async`/`await`

JavaScript, beginner, tutorial, learn-modern-javascript1 min read

Introduction

By the end of this tutorial, you will be able to:

  • apply the async/await pattern to perform asynchronous operations

Asynchronous Programming with async/await

In the not-so-distant past, developers typically relied on promise chains to handle asynchronous logic, which would quickly lead to messy and unreadable code.

async/await statements greatly simplify the syntax for making asynchronous calls with JavaScript. They make asynchronous code look like synchronous code.

Functions declared with async always return a promise. For example:

1const greet = async () => "hello"; // async implicitly wraps 'hello' in a promise
2console.log(greet); // returns a Promise object
3
4greet.then((greeting) => console.log(greeting)); // logs 'hello'

...is equivalent to:

1const greet = async () => Promise.resolve("hello");
2console.log(greet()); // returns a Promise object

await pauses function execution at the awaited line until the promise is either resolved or rejected with a result. It only works inside async functions!

Take a look at the following code:

1const smileAfterDelay = (delay) => {
2 return new Promise((resolve) => {
3 setTimeout(() => {
4 resolve("😁");
5 }, delay);
6 });
7};
8
9const smiley = await smileAfterDelay(2000);
10console.log(smiley);
11
12const smileAtMe = async () => {
13 const smiley = await smileAfterDelay(3000); // wait on this line until promise is resolved or rejected
14 console.log(smiley);
15};
16
17smileAtMe(); // 😁 <-- after 3 seconds

The function at line 9 will not work because the await smileAfterDelay() is not inside an async function, but the function at line 17 would return a 😁 after 3 seconds.

Using async/await with the fetch() method

The built-in JavaScript Fetch API, which is promise-based, is a prime candidate for handling with async/await.

Take a look at the code below:

1const fetchTrivia = () => {
2 fetch("https://opentdb.com/api.php?amount=1&category=18")
3 .then((response) => response.json())
4 .then((data) => {
5 console.log(data.results[0]);
6 })
7 .catch(console.error);
8};

The fetchTrivia() function that performs a GET request using fetch() to a public API, extracts the information from the returned JSON response, and logs the result to the console. The response is handled by chaining promise methods (i.e., .then(), .catch()) to the end of the fetch() method

But if an operation depends on multiple API calls, the syntax above quickly results in a Promise Hell.

ES6 offers a better alternative. Here's the same function written with async/await:

1const fetchTrivia = async () => {
2 try {
3 const response = await fetch(
4 "https://opentdb.com/api.php?amount=1&category=18"
5 );
6 const data = await response.json();
7 console.log(data.results[0]);
8 } catch (error) {
9 console.error(error);
10 }
11};

Wrapping the fetch() call in a try/catch block allows errors to be handled in the catch block.

Want more content like this? Subscribe to get the latest updates in your inbox

Share your Feedback

What did you like or didn't like about this post? Let me know what worked well and what can be improved. Your feedback is much appreciated!