How can I fetch an array of URLs with Promise.all?
Solution 1:
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 text
s 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 => {
…
})
or the same thing with await
:
const texts = await Promise.all(urls.map(async url => {
const resp = await fetch(url);
return resp.text();
}));
Solution 2:
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.
});
Solution 3:
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 => {
// ...
});