Sulla base del titolo della domanda "Risolvi le promesse una dopo l'altra (cioè in sequenza)?", Potremmo capire che l'OP è più interessato alla gestione sequenziale delle promesse di liquidazione rispetto alle chiamate sequenziali di per sé .
Questa risposta è offerta:
- per dimostrare che le chiamate sequenziali non sono necessarie per la gestione sequenziale delle risposte.
- esporre modelli alternativi praticabili ai visitatori di questa pagina, incluso l'OP se è ancora interessato più di un anno dopo.
- nonostante l'affermazione del PO di non voler effettuare chiamate contemporaneamente, il che può essere davvero il caso, ma allo stesso modo può essere un presupposto basato sul desiderio di una gestione sequenziale delle risposte come suggerisce il titolo.
Se le chiamate simultanee non sono veramente richieste, vedere la risposta di Benjamin Gruenbaum che copre in modo completo le chiamate sequenziali (ecc.).
Se tuttavia sei interessato (per migliorare le prestazioni) a schemi che consentono chiamate simultanee seguite da una gestione sequenziale delle risposte, continua a leggere.
È allettante pensare di dover usare Promise.all(arr.map(fn)).then(fn)
(come ho fatto molte volte) o lo zucchero di fantasia di una Promise lib (in particolare di Bluebird), tuttavia (con il merito di questo articolo ) uno arr.map(fn).reduce(fn)
schema farà il lavoro, con i vantaggi che:
- funziona con qualsiasi lib promessa - anche versioni pre-conformi di jQuery - solo
.then()
viene utilizzato .
- offre la flessibilità di saltare l'errore o lo stop-on-error, a seconda di quale si desideri con un mod a una riga.
Eccolo, scritto per Q
.
var readFiles = function(files) {
return files.map(readFile) //Make calls in parallel.
.reduce(function(sequence, filePromise) {
return sequence.then(function() {
return filePromise;
}).then(function(file) {
//Do stuff with file ... in the correct sequence!
}, function(error) {
console.log(error); //optional
return sequence;//skip-over-error. To stop-on-error, `return error` (jQuery), or `throw error` (Promises/A+).
});
}, Q()).then(function() {
// all done.
});
};
Nota: solo quel frammento, Q()
è specifico di Q. Per jQuery è necessario assicurarsi che readFile () restituisca una promessa jQuery. Con A + libs, le promesse straniere saranno assimilate.
La chiave qui è la sequence
promessa della riduzione , che mette in sequenza la gestione delle readFile
promesse ma non la loro creazione.
E una volta assorbito, forse è un po 'strabiliante quando ti rendi conto che il .map()
palco non è effettivamente necessario! L'intero lavoro, le chiamate parallele e la gestione seriale nell'ordine corretto, possono essere raggiunti da reduce()
soli, oltre al vantaggio aggiuntivo di un'ulteriore flessibilità per:
- convertire da chiamate asincrone parallele a chiamate asincrone seriali semplicemente spostando una linea - potenzialmente utile durante lo sviluppo.
Eccolo, di Q
nuovo.
var readFiles = function(files) {
return files.reduce(function(sequence, f) {
var filePromise = readFile(f);//Make calls in parallel. To call sequentially, move this line down one.
return sequence.then(function() {
return filePromise;
}).then(function(file) {
//Do stuff with file ... in the correct sequence!
}, function(error) {
console.log(error); //optional
return sequence;//Skip over any errors. To stop-on-error, `return error` (jQuery), or `throw error` (Promises/A+).
});
}, Q()).then(function() {
// all done.
});
};
Questo è lo schema di base. Se si volesse anche fornire dati al chiamante (ad es. I file o una loro trasformazione), sarebbe necessaria una variante leggera.