Programming
JavaScript
Asynchronous Programming
Code Development
Web Development

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

Understanding Async and Await in Modern Programming

In the world of programming, particularly when dealing with operations that might take time (like fetching data from the internet or querying a database), it’s crucial to manage these tasks without blocking the application from continuing its other operations. This is where the keywords async and await come into play, primarily in languages like JavaScript, C#, Python (asyncio module), and others that support asynchronous programming.

What are async and await?

async and await are programming constructs designed to streamline the writing of asynchronous code, which can otherwise involve complex nested callbacks or complex promise chains. Here's a basic breakdown:

  • async: This keyword is used to declare a function as asynchronous and enables the use of await within it. An async function returns a promise implicitly, and the return value of the function is used to resolve the promise.
  • await: This keyword is used to pause the execution of the async function until a Promise is settled (either resolved or rejected). The keyword can only be used inside an async function.

How to Use async and await

Consider a scenario in which you need to fetch user data from an API and then perform some operations with this data. Here’s how you would traditionally do this using promises:

javascript
1function getUserData(userId) {
2    fetch(`https://api.example.com/users/${userId}`)
3        .then(response => response.json())
4        .then(userData => console.log(userData))
5        .catch(error => console.error("Failed to fetch user data:", error));
6}

Now, let’s refactor this using async and await:

javascript
1async function getUserData(userId) {
2    try {
3        const response = await fetch(`https://api.example.com/users/${userId}`);
4        const userData = await response.json();
5        console.log(userData);
6    } catch (error) {
7        console.error("Failed to fetch user data:", error);
8    }
9}

Notice how the async and await version provides a more synchronous, straightforward code flow, which is easier to read and maintain.

Best Practices for Using async and await

  • Error Handling: Use try/catch blocks to handle errors in async functions. This method handles synchronous and asynchronous errors equally well.
  • Avoid await in Loops: Directly using await inside loops, particularly loops running over operation creating new promises (like fetching URL data), can lead to performance issues. Instead, you can use Promise.all to wait for all promises to be resolved.
  • Use with IIFE: If you need to use await at the top-level code, you can wrap it in an Immediately Invoked Function Expression (IIFE).

Here’s an example of using async-await with IIFE:

javascript
1(async () => {
2    const userData = await getUserData(1);
3    const userProfile = await getUserProfile(userData.id);
4    console.log(userProfile);
5})();

When to Use async and await

async and await are incredibly useful, but they're not always the right solution. Here are some considerations:

  • Use them for clearer, more readable code when dealing with a series of asynchronous operations that depend on each other.
  • Use traditional promises and callbacks for simpler tasks to avoid the overhead of async functions if your environment has performance constraints.

Summary of Key Points

KeywordUseScopeAdvantage
asyncDeclare a function as asynchronousFunction levelAllows the use of await, manages returned value as a promise
awaitPause function execution until promise settlesWithin async functionsSimplifies handling of promises, prevents callback hell

Conclusion

async and await enhance JavaScript's (and other languages') handling of asynchronous operations. They allow developers to write cleaner, more intuitive code while maintaining a high level of performance. Proper usage of these constructs can significantly simplify the complexity of working with asynchronous code and can help build more scalable and robust 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.