Async Network Requests: For Loop vs. .map() + Promise.all()?

When you have multiple asynchronous network requests in JavaScript, you usually have two main options: using a for loop or employing Array.map() along with Promise.all().

So, which one should you choose, and when?

When you want to maintain the order of requests and ensure that each request completes before moving on to the next iteration, using a for of loop is suitable. The loop will await each request.

async function sequentialRequests(urls) {
  const results = [];
  for (const url of urls) {
    const response = await fetch(url);
    const data = await response.json();
    results.push(data);
  }
  return results;
}

On the other hand, when you use map with Promise.all(), all the requests are made at once, and they are put into an array. The Promise.all() then awaits the entire array until every request is completed. If maintaining the order of requests is not crucial and better performance is desired, you can consider using Array.map() with Promise.all().

async function parallelRequests(urls) {
  const promises = urls.map(async (url) => {
    const response = await fetch(url);
    return response.json();
  });

  return Promise.all(promises);
}

I have created a set of resources for learning asynchronous JavaScript. These guides—Callbacks, Promises, and Async/Await —cover everything I’ve learned from years of real-world JavaScript experience.

If you found this article helpful, you’ll get so much out of these guides. Each one is optimized for those “lightbulb moments,” building a strong mental model for how asynchronous JavaScript works and how you can use it to create fast, dynamic applications.