Javascript 如何使用 Promise.all 获取 URL 数组?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31710768/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I fetch an array of URLs with Promise.all?
提问by Bergi
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 Promise
s.
我一直在努力学习用 来做到这一点fetch
,这当然会返回Promise
s。
Some things I've tried that don'twork:
有些事情我已经试过了没有工作:
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'].
这看起来不对,无论如何它都不起作用——我最终没有得到一个数组 ['one', 'two', 'three']。
Is using Promise.all
the right approach here?
Promise.all
在这里使用正确的方法吗?
回答by Bergi
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
是正确的方法,但是如果您想首先fetch
获取所有 url,然后从中获取所有text
s(这也是响应正文的承诺),则实际上需要它两次。所以你需要做
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).
您当前的代码不起作用,因为不forEach
返回任何内容(既不是数组也不是承诺)。
Of course you can simplify that and start with getting the body from each response right after the respective fetch promise fulfilled:
当然,您可以简化它,并在相应的 fetch 承诺完成后立即从每个响应中获取主体:
Promise.all(urls.map(url =>
fetch(url).then(resp => resp.text())
)).then(texts => {
…
})
回答by peirix
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.
出于某种原因,Bergi 的两个例子都不适合我。它只会给我空洞的结果。经过一些调试后,似乎承诺会在获取完成之前返回,因此结果为空。
However, Benjamin Gruenbaum had an answer here earlier, but deleted it. His method didwork 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.
但是,本杰明·格鲁恩鲍姆(Benjamin Gruenbaum)早些时候在这里有一个答案,但删除了它。他的方法确实对我有用,所以我只是将它复制粘贴到这里,作为替代方法,以防其他人在这里遇到第一个解决方案的任何问题。
var promises = urls.map(url => fetch(url).then(y => y.text()));
Promise.all(promises).then(results => {
// do something with results.
});
回答by evgenAborigen
You should use map
instead of forEach
:
您应该使用map
代替forEach
:
Promise.all(urls.map(url => fetch(url)))
.then(resp => Promise.all( resp.map(r => r.text()) ))
.then(result => {
// ...
});