DEV Community

Hamza Khan
Hamza Khan

Posted on

๐Ÿ”„ Async/Await vs Promise.all() โ€” When to Use What?

Asynchronous JavaScript has come a long wayโ€”from callback hell to Promises and now the elegant async/await syntax. But even in modern code, developers often ask:

โ€œShould I use async/await or Promise.all()?โ€

Letโ€™s settle the debate with clear examples, performance comparisons, and best practices in 2025.

๐Ÿง  The Core Difference

  • async/await: Executes asynchronous operations sequentially, unless used with Promise.all.
  • Promise.all(): Executes multiple promises in parallel and waits for all of them to resolve (or reject).

โšก Sequential vs Parallel

Letโ€™s say you need to make 3 API calls.

โŒ Sequential Execution (async/await)

const getData = async () => {
  const a = await fetchDataA(); // wait
  const b = await fetchDataB(); // wait
  const c = await fetchDataC(); // wait
  return [a, b, c];
};
Enter fullscreen mode Exit fullscreen mode

Time taken โ‰ˆ fetchDataA + fetchDataB + fetchDataC

โœ… Parallel Execution (Promise.all)

const getData = async () => {
  const [a, b, c] = await Promise.all([
    fetchDataA(),
    fetchDataB(),
    fetchDataC(),
  ]);
  return [a, b, c];
};
Enter fullscreen mode Exit fullscreen mode

Time taken โ‰ˆ max(fetchDataA, fetchDataB, fetchDataC)

๐Ÿง  Use Promise.all() when tasks are independent and can run in parallel.

๐Ÿ’ฅ What About Errors?

Promise.all() Fails Fast:

try {
  const [a, b] = await Promise.all([failingFunc(), successFunc()]);
} catch (err) {
  console.error('At least one failed:', err);
}
Enter fullscreen mode Exit fullscreen mode

If any promise rejects, the entire Promise.all() rejects.

Want All Results No Matter What? Use Promise.allSettled():

const results = await Promise.allSettled([
  mightFail1(),
  mightFail2(),
]);

results.forEach((result) => {
  if (result.status === 'fulfilled') console.log(result.value);
  else console.error(result.reason);
});
Enter fullscreen mode Exit fullscreen mode

๐Ÿ” Looping with Async Ops

Hereโ€™s where async/await shines: inside loops.

โŒ Not Ideal

for (const user of users) {
  await sendEmail(user); // sequential, slow
}
Enter fullscreen mode Exit fullscreen mode

โœ… Better: Use Promise.all with .map()

await Promise.all(users.map(user => sendEmail(user)));
Enter fullscreen mode Exit fullscreen mode

๐Ÿš€ This sends emails in parallel. Much faster.

๐Ÿง  TL;DR โ€” When to Use What?

Use Case Use async/await Use Promise.all()
Tasks must run sequentially โœ… โŒ
Tasks are independent โŒ โœ…
You need all results, even fails โŒ โœ… Promise.allSettled()
Error handling per task โœ… โŒ
Inside a loop โœ… (small data) โœ… .map() + Promise.all for large data

๐Ÿงช Bonus: Performance Benchmark

For I/O-bound operations like API calls or DB queries, parallel execution with Promise.all() significantly improves response time. For CPU-bound tasks, consider using Web Workers or moving to a language like Go or Rust.

โœจ Final Thoughts

In 2025, writing performant async code is less about picking one method and more about understanding concurrency.

  • โœ… Use async/await for readability.
  • โœ… Use Promise.all() for speed.
  • โœ… Combine both when necessary!

Top comments (0)