2015-07-29 14 views
18

Se ho una serie di URL:Come posso recuperare un array di URL con Promise.all?

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

E voglio costruire un oggetto che assomiglia a questo:

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

Ho cercato di imparare a fare questo con fetch, che naturalmente restituisce Promise s.

Alcune cose che ho provato che non lo fanno lavoro:

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

Questo non guardare a destra, e in ogni caso non funziona - io non finire con un array ['one', 'two', 'three'].

Sta usando Promise.all l'approccio giusto qui?

+0

Che assomiglia a un errore di bracketing. Volevi davvero chiamare '.then' sul valore di ritorno di' .forEach (...) ', o piuttosto su' ... .text() '? – Bergi

+0

Dove guardate/registrate 'testi' e osservate che è ancora vuoto? – Bergi

risposta

39

Sì, Promise.all è l'approccio giusto, ma in realtà bisogno di due volte se si vuole prima fetch tutti gli URL e quindi ottenere tutte le text s da loro (che ancora una volta sono promesse per il corpo della risposta). Così avresti bisogno di fare

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

Il codice attuale non funziona perché forEach restituisce nulla (né una matrice, né una promessa).

Naturalmente è possibile semplificare questo e iniziare con ottenere il corpo da ogni risposta subito dopo il rispettivo promessa prendere soddisfatte:

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

Indirizzamento a qualcosa che ho percepito nella domanda: Non è possibile "estrarre" i risultati in una variabile esterna a causa di come funziona async in JavaScript, ma è possibile utilizzare generatori o async/attendere per simularlo. Vedi [questa risposta] (http://stackoverflow.com/a/30180679/1348195) per una guida completa sull'asincronizzazione in JS. –

+0

questo sembra incredibile! ma non posso girare la testa :(javascript è una lingua strana – yota

12

Per qualche motivo nessuno dei esempi di Bergi lavorato per me. Mi avrebbe semplicemente dato risultati vuoti. Dopo un po 'di debug sembra che la promessa sarebbe tornata prima che il recupero fosse finito, quindi i risultati vuoti.

Tuttavia, Benjamin Gruenbaum aveva una risposta qui prima, ma l'ha cancellato. Il suo metodo ha funzionato per me,, quindi mi limiterò a copiare e incollare qui, come alternativa nel caso in cui qualcun altro si imbattesse in qualche problema con la prima soluzione qui.

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

Si consiglia di utilizzare map invece di forEach:

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