How can I fetch an array of URLs with Promise.all?

If I have an array of urls:

var urls = ['1.txt', '2.txt', '3.txt']; // these text files contain "one", "two", "three", respectively.

And I want to build an object that looks like this:

var text = ['one', 'two', 'three'];

I’ve been trying to learn to do this with fetch, which of course returns Promises.

Some things I’ve tried that don’t work:

var promises = urls.map(url => fetch(url));
var texts = [];
Promise.all(promises)
  .then(results => {
     results.forEach(result => result.text()).then(t => texts.push(t))
  })

This doesn’t look right, and in any case it doesn’t work — I don’t end up with an array ['one', 'two', 'three'].

Is using Promise.all the right approach here?

Yes, Promise.all is the right approach, but you actually need it twice if you want to first fetch all urls and then get all texts from them (which again are promises for the body of the response). So you'd need to do

Promise.all(urls.map(u=>fetch(u))).then(responses =>
    Promise.all(responses.map(res => res.text()))
).then(texts => {
    …
})

Your current code is not working because forEach returns nothing (neither an array nor a promise).

Of course you can simplify that and start with getting the body from each response right after the respective fetch promise fulfilled:

Promise.all(urls.map(url =>
    fetch(url).then(resp => resp.text())
)).then(texts => {
    …
})

Promise API, For instance, if we have an array of URLs, we can fetch them all like this: let urls = [ 'https://api.github.com/users/iliakan'  Using Fetch API with Promise.all. return fetch(url) in map then how can i check my the results of all the promises are returned as an array un the order they

For some reason neither of Bergi's examples worked for me. It would simply give me empty results. After some debugging it seemes like the promise would return before the fetch had finished, hence the empty results.

However, Benjamin Gruenbaum had an answer here earlier, but deleted it. His method did work for me, so I'll just copy-paste it here, as an alternative in case anyone else runs into any problems with the first solution here.

var promises = urls.map(url => fetch(url).then(y => y.text()));
Promise.all(promises).then(results => {
    // do something with results.
});

Quickly mapping an array of URLs to responses with JavaScript , "https://jsonplaceholder.typicode.com/comments/3" ]; async function fetchAll() { const results = await Promise.all(urls.map((url) => fetch(url).then((r) => r.json()))); Remember, the fetch data functions passed to promise.all, already. 2:37. handle checking the response status and converting the response to JSON. 2:42. So the first object in the array contains the list of breeds, 2:48. since that's what we passed first to Promise.all, and. 2:52. the second object contains the image URL. 2:58

You should use map instead of forEach:

Promise.all(urls.map(url => fetch(url)))
.then(resp => Promise.all( resp.map(r => r.text()) ))
.then(result => {
    // ...
});

Manage Multiple Requests with Promise.all, Promise.all joins two or more promises and returns only when all the specified store urls to fetch in an array const urls = [ 'https://dog.ceo/api/breeds/list',  When you use fetch( ) to make your AJAX calls, you will be returned a Promise object. That is why we use then( ) and catch( ) with fetch( ). That means we can use Promise.all( ) and wait for all

Sync up multiple Promises to a single result set with Promise.all, As soon as map has finished iterating through our url array, it returns an array of Promises that are asynchronously fetching data from our URLs  To make things faster, once any of the inner promises rejects, Promise.all() rejects. The main point is that Promise.all() turns an array of promises into a single promise that, if things work, resolves into the array you want. Everything else is just details. Somehow, it took me a long time to get unstuck.

Using the JavaScript Fetch API - Sophia Shoemaker, The fetch() method takes two parameters — the URL that you are requesting (or a Request object) The Promise.all() method takes an array of Promise objects. The best solution is to use Promise.all which waits for an array of promises (fetch is a promise) to all resolve, after which you can process the data. Here I've created a dummy fetch function with some sample data to quickly show you how that works.

Async/await function to fetch data from multiple URLs in parallel , Async/await function to fetch data from multiple URLs in parallel - async.js. Promise.all() lets us coalesce multiple promises into a single super-promise. var data = await Promise.all([. /* Alternatively store each in an array */. // var [x, y, z]  promise.all takes an array of promise objects, created from the return values of functions you have called already. "Now, I can put all functions in an array and can do Promise.all(array of functions)" will not call the functions, and would resolve the returned promise with a reconstructed copy of the input array. – traktor53 Mar 19 '16 at 6:10

Comments
  • That looks like a bracketing mistake. Did you really intend to call .then on the return value of .forEach(…), or rather on ….text()?
  • Where do you look at / log texts and observe it to be still empty?
  • Addressing something I sensed in the question: You can't "extract" results to an outside variable because of how async works in JavaScript, but you can use generators or async/await to simulate it. See this answer for a complete guide on asynchronisity in JS.
  • this looks amazing ! but I can't wrap my head around :( javascript is a strange language
  • @sansSpoon Are you sure you used the concise arrow body that I have in my answer? It does implicitly return the promise.
  • Doh, of course, palm > face. I'm always mixing my es5/6. Thanks.
  • @1252748 Yes, the Promise.all() returns a single promise for an array or response objects. But then, responses.map(res => res.text()) produces another array of promises which needs a second Promise.all.
  • why use map instead of forEach? just to ask?
  • @ChristianMatthew map returns each result of fetch(url) while forEach doesn't return anything. See either the accepted answer or stackoverflow.com/a/34426481/1639983.
  • thanks @HoldenLewis that is the answer i was thinking of