Как я могу получить массив URL-адресов с помощью Promise.all?
Если у меня есть массив URL-адресов:
var urls = ['1.txt', '2.txt', '3.txt']; // these text files contain "one", "two", "three", respectively.
И я хочу построить объект, который выглядит так:
var text = ['one', 'two', 'three'];
Я пытался научиться делать это с помощью fetch
, что, конечно же, возвращает Promise
s.
Некоторые вещи, которые я пытался, не работают:
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
правильный подход здесь?
Ответы
Ответ 1
Да, Promise.all
- правильный подход, но он вам действительно нужен дважды, если вы хотите сначала fetch
все URL-адреса, а затем получить от них весь text
(что опять-таки является обещаниями для основной части ответа). Так что вам нужно сделать
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 => {
…
})
Ответ 2
По какой-то причине ни один из примеров Берги не работал для меня. Это просто даст мне пустые результаты. После некоторой отладки кажется, что обещание вернется до того, как выборка закончится, а значит, и пустые результаты.
Однако Бенджамин Груэнбаум ответил здесь ранее, но удалил его. Его метод действительно работал для меня, поэтому я просто скопирую его здесь, в качестве альтернативы, если кто-то еще столкнется с какими-либо проблемами с первым решением здесь.
var promises = urls.map(url => fetch(url).then(y => y.text()));
Promise.all(promises).then(results => {
// do something with results.
});
Ответ 3
Вы должны использовать map
вместо forEach
:
Promise.all(urls.map(url => fetch(url)))
.then(resp => Promise.all( resp.map(r => r.text()) ))
.then(result => {
// ...
});