Ho una matrice che contiene nomi di file in ogni indice. Voglio scaricare quei file uno alla volta (in modo sincrono). Conosco il modulo 'Async
'. Ma voglio sapere se alcune funzioni nella libreria Lodash
o nella libreria Bluebird
supportano questa funzionalità.Come iterare un array in modo sincrono usando lodash, underscore o bluebird
risposta
È possibile utilizzare di Promise.mapSeries
Bluebird:
var files = [
'file1',
'file2'
];
var result = Promise.mapSeries(files, function(file) {
return downloadFile(file); // << the return must be a promise
});
A seconda di quello che si utilizza per scaricare il file, potrebbe essere necessario costruire una promessa o no.
Aggiornamento 1
Un esempio di una funzione downloadFile()
utilizzando solo nodejs:
var http = require('http');
var path = require('path');
var fs = require('fs');
function downloadFile(file) {
console.time('downloaded in');
var name = path.basename(file);
return new Promise(function (resolve, reject) {
http.get(file, function (res) {
res.on('data', function (chunk) {
fs.appendFileSync(name, chunk);
});
res.on('end', function() {
console.timeEnd('downloaded in');
resolve(name);
});
});
});
}
Aggiornamento 2
Come suggerito Gorgi Kosev, la costruzione di una catena di promesse utilizzando un ciclo funziona anche:
var p = Promise.resolve();
files.forEach(function(file) {
p = p.then(downloadFile.bind(null, file));
});
p.then(_ => console.log('done'));
Una catena di promesse ti porterà solo il risultato dell'ultima promessa della catena mentre mapSeries()
ti offre un array con il risultato di ogni promessa.
utilizzando Bluebird, c'è una situazione simile al tuo, con una risposta qui: How to chain a variable number of promises in Q, in order?
Questa sembra una soluzione decente, ma a mio parere molto meno leggibile ed elegante come async.eachSeries (So che hai detto te Non voglio la soluzione 'asincrona' ma forse puoi riconsiderare:
Senza mapSeries: 'var downloads = []; per (var p = Promise.pending(), i = 0; i downloadFile (files [i]))); return Promise.all (download) ' –
@GorgiKosev Il tuo codice non funziona ma sì, costruendo una catena di anche le promesse funzionerebbero, ma usare 'Promise.all()' qui è sbagliato, stai facendo un 'Promise.all ([p, p, p])', ogni file verrà scaricato più volte. Aggiornerò la mia risposta con il tuo suggerimento – Shanoor
No, questo non è corretto. Una promessa rappresenta un'operazione che è già stata avviata e tentare di collegarla più volte non farà ripetere la stessa operazione. È del tutto normale usare "Promise.all" come se fosse giusto allegare più callback "allora" a una singola promessa. –