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

感情迁移 提交于 2019-11-26 06:06:24

问题


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?


回答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 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 => {
    …
})



回答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.
});



回答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 => {
    // ...
});


来源:https://stackoverflow.com/questions/31710768/how-can-i-fetch-an-array-of-urls-with-promise-all

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!