Understanding async/await in Node.js

Lillian Nose

Async/await is a native feature available in Node.js that makes it easier to manage tasks that take time, like waiting for a response from an API. In Node.js, where it’s common to handle many tasks simultaneously, async/await keeps our asynchronous code organized and more readable.

Async/await is a syntactic sugar built on top of promises. In this blog post, you’ll learn how to use async/await in your own code and see how it differs from other syntaxes.

What are promises?

A promise is a placeholder value that will eventually be filled in the future. The idea is similar to the familiar concept of real-world promises. For example, if you make a promise to do the dishes, that is an assurance that the dishes will be done eventually, which lets you continue on with other tasks.

Promises allow an asynchronous operation to run and wait for the value—while also running any following code (called “callbacks”) in the meantime. Callbacks were originally invoked by passing them as an argument. Promises introduced a new syntax of using then/catch statements to chain callbacks together.

This new way of invoking callbacks eliminates the issue that is popularly known as “callback hell” or “promise pyramids,” which occurs when there are multiple chains of callbacks:

firstFunction(args, function() {
  secondFunction(args, function() {
    thirdFunction(args, function() {
      // it can keep going
    });
  });
});

Using then statements to chain functions together is one way to handle promises better, as it allows for more readable code:

firstFunction(args)
  .then(secondFunction(args))
  .then(thirdFunction(args))

How to declare an async function

We know that async/await helps us handle asynchronous operations, but how do we use it?

It’s as easy as declaring a function with the async keyword. All async functions return a promise, automatically encapsulating non-promise values. Functions can be made async by using the keyword async before the function declaration:

async function bakeCookies() {
  // Simulating baking time
  await new Promise((resolve) => setTimeout(resolve, 2000));
}

What is await?

Await is a keyword paired with async functions that causes the JavaScript interpreter to pause until the following asynchronous operation is run. You can also assign the value to a variable to use later. It’s important to remember that the keyword await can only be placed in the bodies of async functions.

async function serveCookies() { 
  const cookies = await bakeCookies();
  console.log("The cookies are now ready to serve!");
}

serveCookies()

If we assume that bakeCookies() in the example above is an asynchronous operation that returns a promise, the await keyword will halt the function serveCookies() until bakeCookies() has returned a value.

Why use async/await?

Use async/await in Node.js when you want to write asynchronous code that is more readable, sequential, and better at error handling.

This approach reduces the cognitive load for developers, making it easier to understand, read, and debug the code. By maintaining a top-to-bottom flow and utilizing try/catch for error handling, async/await simplifies the learning curve for those who are new to asynchronous programming.

Error handling with async/await

Without error handling, rejected promises can lead to unhandled promise errors, which can cause your application to behave unpredictably. Async functions can use try/catch blocks, which enable you to try a bunch of operations within a block and then catch any errors raised during execution to be handled in the catch block.

Let’s look at how the experience of fetching data from an API differs when we use then/catch and async/await. The below snippet shows an example of error handling using then/catch:

// Using promises with .then() and .catch() for error handling

function fetchData() {    
  return fetch('/endpoint')
  .then(response => response.text())
  .then(summary => {
    console.log(summary);    
  })    
  .catch(error => {
    console.log('Error:' + error.message);
  });
}

// Call fetchData()
fetchData();

The following code does the same thing, but it uses async/await instead, making the sequential flow easier to parse through:

async function fetchDataAsync() {
  try {
    const response = await fetch('/endpoint');
    const summary = await response.text();
    console.log(summary);
  } catch (error) {
    console.log('Error:' + error.message);
  }
}

// Call fetchDataAsync()
fetchDataAsync();

Try async/await in a project

Now that you’re familiar with how to use async/await, start by getting hands-on experience through the Postman Student Program’s newest Project-Based Learning module! Learn how to build a full stack AI text summarizer app with the help of Postman, while handling promises with async/await along the way:

Postman Student Programs gives students the opportunity to dive into the fascinating world of APIs, gain valuable insights, and earn a free certificate through comprehensive training. Sign up to gain instant access to our free Postman API Fundamentals Student Expert certification and learning modules in Postman Academy.

What do you think about this topic? Tell us in a comment below.

Comment

Your email address will not be published. Required fields are marked *


This site uses Akismet to reduce spam. Learn how your comment data is processed.