ho fatto alcuni esperimenti di questa mattina, prima di andare a vedere se ho una risposta ... :-)
Potete vederli http://plnkr.co/edit/3Xczzw
ho scoperto che concat di osservabili verrà eseguito ogni osservabile a sua volta, nell'ordine indicato.
var o1 = Rx.Observable.interval(1500).take(1).map(function (i) { return { n: i, id: 'First', ts: Date.now() - reference }});
var o2 = Rx.Observable.interval(1000).take(2).map(function (i) { return { n: i, id: 'Second', ts: Date.now() - reference }});
var o3 = Rx.Observable.interval(2000).take(1).map(function (i) { return { n: i, id: 'Third', ts: Date.now() - reference }});
// Alternative
var oa = Rx.Observable.timer(1200).map(function (i) { return { n: i, id: 'Alternative', ts: Date.now() - reference }});
Rx.Observable.concat(o1, o2, o3, oa).subscribe(
function onNext(v) { v.timestamp = Date.now() - reference; showObject(v); },
function onError(e) { var ts = Date.now() - reference; showHTML("Error " + JSON.stringify(e) + " at " + ts); },
function onCompleted() { var ts = Date.now() - reference; showHTML("Completed at " + ts); }
);
dà
{"n":0,"id":"First","ts":1503,"timestamp":1503}
{"n":0,"id":"Second","ts":2504,"timestamp":2504}
{"n":1,"id":"Second","ts":3505,"timestamp":3505}
{"n":0,"id":"Third","ts":5506,"timestamp":5506}
{"n":0,"id":"Alternative","ts":6708,"timestamp":6708}
Completed at 6708
Un concat di promesse non consegnerà nulla prima della prima promessa si risolve. Quindi può consegnare (cioè chiamare su Avanti) le altre promesse risolte, sempre nell'ordine indicato. Poi vedo l'ora per la prossima promessa se eventuali resti, ecc
var p1 = promiseInTime(1500, { id: 'First'});
var p2 = promiseInTime(1000, { id: 'Second' });
var p3 = promiseInTime(2000, { id: 'Third' });
var pa = promiseInTime(1200, { id: 'Failed? ' + !!withFailure }, withFailure);
Rx.Observable.concat(p1, p2, p3, pa).subscribe(
function onNext(v) { v.timestamp = Date.now() - reference; showObject(v); },
function onError(e) { var ts = Date.now() - reference; showHTML("Error " + JSON.stringify(e) + " at " + ts); },
function onCompleted() { var ts = Date.now() - reference; showHTML("Completed at " + ts); }
);
dà
{"id":"First","promiseTimeout":1500,"timestamp":1501}
{"id":"Second","promiseTimeout":1000,"timestamp":1506}
{"id":"Third","promiseTimeout":2000,"timestamp":2001}
Error {"id":"Failed? true","promiseTimeout":1201} at 2004
o
{"id":"First","promiseTimeout":1500,"timestamp":1501}
{"id":"Second","promiseTimeout":1000,"timestamp":1503}
{"id":"Third","promiseTimeout":2000,"timestamp":2000}
{"id":"Failed? false","promiseTimeout":1201,"timestamp":2004}
Completed at 2004
Quindi, in sostanza, concat rispetta l'ordine degli argomenti, che può essere un modo per ritrovare quale richiesta ha emesso un risultato di promessa.
Nel caso di richieste Ajax, è meglio concatenare le promesse di quelle osservabili, in quanto saranno richieste in parallelo, non in sequenza (a meno che non sia necessario il secondo, ovviamente).
Ho provato la soluzione fornita da @ user3743222, ed è una buona soluzione. Preferisco forkJoin, poiché i risultati sono assegnati esplicitamente ai parametri, invece di fare affidamento sull'ordine.
Devi essere consapevole delle differenze nella gestione degli errori: ho scoperto che concat elaborerà tutte le promesse, fino a quando non viene rilevato il primo errore. Mentre forkJoin non elaborerà nulla se uno degli errori promette. Il che ha senso (non possiamo unirci a risultati parziali, in generale).
Grazie. Ho scoperto come concat funziona davvero (vedi la mia risposta), ma preferisco forkJoin, che corrisponde a ciò che volevo. Ho completamente trascurato questo ... :-) – PhiLho
Se qualcuno sta provando a farlo funzionare in Angular, non lo farà, poiché l'evento "completo" non viene attivato dagli osservabili http. Per una soluzione simile, ha funzionato per me usando invece "combineLatest". – frandevel