JavaScript
async programming
async await
concurrency
programming tutorials

How and when to use ‘async’ and ‘await’

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction to async and await

In modern JavaScript, efficient handling of asynchronous operations is crucial. The introduction of async and await keywords in ECMAScript 2017 (ES8) offers a cleaner and more understandable way to manage promises. This article delves deeply into how and when to use these constructs, providing you with practical examples and comprehensive understanding.

Understanding the Basics

async and await work hand in hand to simplify asynchronous programming in JavaScript. Let's explore their functionalities individually before demonstrating how they work together.

The async Keyword

  • Purpose: The async keyword is used to declare a function as asynchronous, meaning it returns a Promise.
  • Syntax:
javascript
  async function exampleFunction() {
    return 'Hello, World!';
  }

By declaring a function async, it allows you to use await within it and guarantees that the result of the function will be wrapped in a promise:

javascript
1async function exampleFunction() {
2  return 'Hello, World!';
3}
4
5exampleFunction().then(console.log); // Output: Hello, World!

The await Keyword

  • Purpose: The await keyword is used within an async function to pause the execution of the function until a Promise is resolved or rejected.
  • Syntax:
javascript
1  async function exampleFunction() {
2    const result = await somePromise;
3    console.log(result);
4  }

When using await, the function execution pauses until the Promise settles, then resumes with the resolved value. Note that await can only be used inside async functions.

Practical Examples

Below are practical examples that showcase how async and await can be used in real-world scenarios.

Fetch API Example

javascript
1async function fetchData(url) {
2  try {
3    const response = await fetch(url);
4    if (!response.ok) {
5      throw new Error('Network response was not ok');
6    }
7    const data = await response.json();
8    console.log(data);
9  } catch (error) {
10    console.error('Fetch error:', error);
11  }
12}
13
14fetchData('https://api.example.com/data');

Error Handling

Error handling in asynchronous code becomes straightforward with try...catch blocks:

javascript
1async function getUserData(userId) {
2  try {
3    const response = await fetch(`/users/${userId}`);
4    const userData = await response.json();
5    return userData;
6  } catch (error) {
7    console.error('Failed to fetch user data:', error);
8    throw error; // Re-throwing the error for further handling
9  }
10}

When to Use async and await

Use Cases

  1. Network Requests: When calling APIs or fetching resources over the network.
  2. I/O Operations: For file manipulation or database queries, which are inherently asynchronous and IO-bound.
  3. Sequential Execution: When operations depend on each other, await helps manage the sequence naturally.

Advantages

  • Readability: Code using async and await is generally more readable and maintainable compared to chained Promises.
  • Error Handling: Simplifies catching and handling errors with try...catch.
  • Sequential and Parallel Logic: Easily manage sequential logic or, if required, run concurrent operations using Promise.all().

Limitations

  • Inside Async Functions: You can only use await within functions marked as async.
  • Top-Level Await: Not natively supported outside modules, though modern environments may support under specific conditions.

Summary in Table Format

FeatureKey Points
async- Declares an asynchronous function - Returns a Promise implicitly
await- Pauses async function execution - Waits for Promise resolution
Advantages- Enhanced readability - Simplified error handling with try...catch
Use Cases- Network requests - IO-bound operations - Sequential logic management
Limitations- Restricted to async functions - Top-level await has limited support

Advanced Topics

Handling Multiple Promises

An advanced technique for handling multiple promises in parallel can be accomplished using Promise.all(), which works seamlessly with async and await:

javascript
1async function getMultipleData(urls) {
2  try {
3    const promises = urls.map(url => fetch(url).then(res => res.json()));
4    const results = await Promise.all(promises);
5    console.log(results);
6  } catch (error) {
7    console.error('Error fetching multiple resources:', error);
8  }
9}

Using async with Arrow Functions

Arrow functions can also be asynchronous:

javascript
1const asyncArrowFunction = async () => {
2  const response = await fetch('/some-endpoint');
3  const data = await response.json();
4  return data;
5};

Conclusion

The async and await keywords bring a robust solution to handling asynchronous operations in JavaScript. They offer a more intuitive way to work with promises, similar to writing synchronous code. By comprehensively understanding their use cases, limitations, and advantages, you can greatly enhance the efficiency and maintainability of your JavaScript applications.


Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.