Programming Language
JavaScript
Synchronous and Asynchronous
Async Await

Understanding async and await in JavaScript

In JavaScript, managing asynchronous tasks can be achieved in various ways, including callbacks and promises. A modern approach for handling asynchronous operations is by using async and await. This article explains what async and await are, how they work, and how they can simplify your code, using straightforward examples.

What is async?

The async keyword is used to define an asynchronous function. An async function always returns a promise. If you return a value from an async function, JavaScript automatically wraps it in a resolved promise.

Example of async Function

async function fetchData() {
  return 'Data fetched';
}
 
fetchData().then((data) => {
  console.log(data); // Output: Data fetched
});

In this example, fetchData is an asynchronous function that returns a promise. The promise resolves with the string 'Data fetched'.

What is await?

The await keyword can only be used inside an async function. It pauses the execution of the async function until the promise it is waiting for is either resolved or rejected. This allows you to write asynchronous code that looks synchronous, making it easier to understand.

Example of await with async

async function fetchData() {
  let data = await new Promise((resolve) => {
    // Simulating an asynchronous operation
    resolve('Data fetched');
  });
  console.log(data); // Output: Data fetched
}
 
fetchData();

In this example, fetchData uses await to wait for the promise to resolve. The function pauses at await until the promise resolves, then logs the result.

How async and await Work Together

When you use async and await together, you can write code that is both clean and easy to understand. Here’s a simple explanation:

  • Declare an async Function: Use async to define a function that can handle asynchronous tasks.
  • Use await Inside the async Function: Use await to wait for promises to resolve before continuing execution.
async function getUserData() {
  console.log('Fetching user data...');
  
  // Simulating fetching user data
  let userData = await new Promise((resolve) => {
    resolve({ name: 'John', age: 30 });
  });
  
  console.log('User data received:', userData);
}
 
getUserData();

In this example:

  • The getUserData function is declared as async.
  • Inside the function, await pauses execution until the promise resolves, simulating a data fetch.
  • Once resolved, the user data is logged to the console.

Error Handling with async/await

To handle errors in async functions, you can use try and catch blocks. This allows you to manage exceptions that might occur during asynchronous operations.

async function getData() {
  try {
    let data = await new Promise((resolve, reject) => {
      // Simulating an operation that could fail
      reject('Failed to fetch data');
    });
    console.log(data);
  } catch (error) {
    console.error('Error:', error); // Output: Error: Failed to fetch data
  }
}
 
getData();

In this example:

  • The try block attempts to execute the asynchronous operation.
  • If the promise is rejected, the catch block handles the error and logs it.

Conclusion

async and await offer a streamlined way to handle asynchronous operations in JavaScript. By defining async functions and using await to wait for promises, you can write more readable and manageable asynchronous code. Error handling with try and catch ensures that your code remains robust and reliable.