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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 07:04:42  来源:igfitidea点击:

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

javascriptpromisees6-promisefetch-api

提问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 Promises.

我一直在努力学习用 来做到这一点fetch,这当然会返回Promises。

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.allthe right approach here?

Promise.all在这里使用正确的方法吗?

回答by Bergi

Yes, Promise.allis the right approach, but you actually need it twice if you want to first fetchall 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是正确的方法,但是如果您想首先fetch获取所有 url,然后从中获取所有texts(这也是响应正文的承诺),则实际上需要它两次。所以你需要做

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 forEachreturns 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 mapinstead of forEach:

您应该使用map代替forEach

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