DEV Community

Cover image for Async Await Best Practices: Tips and Tricks for Faster, Smarter Code
sanuj bansal
sanuj bansal

Posted on

Async Await Best Practices: Tips and Tricks for Faster, Smarter Code

Asynchronous programming has become an essential part of modern web development, allowing developers to write code that is both efficient and responsive. However, when it comes to working with async functions, there are some common mistakes that developers often make.

In this article, we will take a look at an example of how to use Async Await, and discuss some of the mistakes that can occur when using this method. We will also explore some alternative approaches that can help to avoid these mistakes and make your code more efficient.

Let’s start by looking at some code:

const ids = ['1', '2', '3'];
const getData = () => {
 for (const id in ids) {
 axios.get(`${baseUrl}?id=${id}`).then((data) => {
 // You can save the data here
 });
 }
 console.log('Data fetched successfully');
}
getData();
Enter fullscreen mode Exit fullscreen mode

At first glance, this code seems to be working fine. However, it has a significant problem. The console.log statement that should run after the data is fetched will execute even before the data is fetched, which is not desirable.

To fix this issue, we can use async/await like so:

const ids = ['1', '2', '3'];
const getData = async () => {
 for (const id in ids) {
 await axios.get(\`${baseUrl}?id=${id}\`);
 }
 console.log('Data fetched successfully');
}
getData();
Enter fullscreen mode Exit fullscreen mode

Now, the console.log statement executes only after the data is fetched. But there’s a problem: the code takes N times as long to execute since each Axios request must complete before the next can start, making the code synchronous and slow.

A better solution to this problem is to use Promise.all to execute all promises asynchronously and wait for them to resolve:

const ids = ['1', '2', '3'];
const getData = async () => {
 const promises = [];
 for (const id in ids) {
 promises.push(axios.get(`${baseUrl}?id=${id}`));
 }
 const results = await Promise.all(promises);
 // you will get results in the form of an array with the 
 // order preserved
 console.log('Data fetched successfully');
}
getData();
Enter fullscreen mode Exit fullscreen mode

Using Promise.all ensures that all the promises execute asynchronously and waits for all of them to resolve. This helps you maintain the speed of processing while also letting you wait for the response. However, it’s important to note that even if one of the network calls fails, the rest of the promises will not be executed, and your code will throw an exception.

To handle errors more gracefully, ES2020 introduced the Promise.allSettled method. This method helps you handle errors more easily, as shown in the following code:

const getData = async () => {
 const promises = [];
 for (const id in ids) {
 promises.push(axios.get(`${baseUrl}?id=${id}`));
 }
 const results = await Promise.allSettled(promises);
 results.map((result) => {
 // Check if the promise was fulfilled or it failed
 if (result.status === 'fulfilled') {
 // You can do anything here with the result.value
 }
 })
 console.log('Data fetched successfully');
}
getData();
Enter fullscreen mode Exit fullscreen mode

Promise.allSettled helps you handle errors with ease by ensuring that all promises are settled, regardless of whether they’re fulfilled or rejected.

In conclusion, Async Await is a powerful tool for asynchronous programming, but it requires careful handling to avoid common mistakes. Using Promise.all and Promise.allSettled can help you avoid these pitfalls and make your code more robust.

Top comments (0)