79

URLの配列がある場合:

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

そして、次のようなオブジェクトを構築したいと思います。

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

私は でこれを行うことを学ぼうとしてきましたがfetch、これはもちろんPromises を返します。

私が試したいくつかのことはうまくいきません

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

これは正しくないように見えますが、いずれにせよ機能しません — 配列 ['one', 'two', 'three'] にはなりません。

Promise.allここで正しいアプローチを使用していますか?

4

6 に答える 6

145

はい、正しいアプローチですが、最初にすべての URL を取得し、次にそれらからすべての を取得Promise.allする場合は、実際には 2 回必要です(これも応答の本文の約束です)。だからあなたはする必要がありますfetchtext

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

forEach何も返さないため (配列もプロミスも返さない)、現在のコードは機能していません。

もちろん、それを単純化して、それぞれの fetch promise が満たされた直後に各レスポンスから本文を取得することから始めることができます:

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

または同じことawait

const texts = await Promise.all(urls.map(async url => {
  const resp = await fetch(url);
  return resp.text();
}));
于 2015-07-29T21:29:57.077 に答える
13

mapの代わりに使用する必要がありますforEach

Promise.all(urls.map(url => fetch(url)))
.then(resp => Promise.all( resp.map(r => r.text()) ))
.then(result => {
    // ...
});
于 2016-05-26T11:06:10.897 に答える
1

ここにそれを行うためのきれいな方法があります。

const requests = urls.map((url) => fetch(url)); 
const responses = await Promise.all(requests); 
const promises = responses.map((response) => response.text());
return await Promise.all(promises);
于 2021-10-08T05:59:48.220 に答える