web-dev-qa-db-ja.com

Promise.allでURLの配列を取得するにはどうすればよいですか?

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ここで正しいアプローチ?

41
user2467065

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

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

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

もちろん、それを単純化して、それぞれのフェッチプロミスが満たされた直後に各応答から本文を取得することから始めることができます。

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

なんらかの理由で、ベルギの例はどちらもうまくいきませんでした。単純に空の結果が得られます。デバッグ後、フェッチが完了する前にプロミスが返されるように見えるため、結果は空になります。

しかし、ベンジャミン・グリュンバウムは以前ここで答えを持っているが、それを削除した。彼の方法did私のために働くので、ここで最初の解決策で他の誰かが問題に遭遇した場合の代替として、ここにコピーアンドペーストします。

var promises = urls.map(url => fetch(url).then(y => y.text()));
Promise.all(promises).then(results => {
    // do something with results.
});
18
peirix

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

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