2016-08-30 6 views
2

JSBIN SamplecombineAll emittiert nicht leeres Array

I einen veränderbaren Satz von untergeordneten Komponenten hat (POJO Objekt), die jeweils ihren eigenen Zustand Strom haben. Jedes Mal, wenn ein Benutzer addChild/removeChild/clearChildren auslöst, wird mit #switchMap eine neue Gruppe von untergeordneten Status-Streams ausgegeben. So weit, ist es gut! (Und so überrascht von RxJS!)

Mit Rx.Observable.from(arrayOfStateStreams).combineAll() bekomme ich ein gutes Ergebnis, solange die arrayOfStateStreams kein leeres Array ist.

Da dies ein partieller Zustand ist, der auf einer höheren Ebene (Latest) kombiniert wird, muss ich ein leeres Array emittieren oder der globale Zustandsbaum enthält alte Zustandsdaten, die nicht mehr wahr sind!

Ich kann einige reservierte Token wie ['EMPTY-ARRAY-PLACEHOLDER-TOKEN'] ausgeben, aber das ist nur komisch. Ein besserer Weg wäre, immer einen letzten Strom an das Array anzuhängen, so dass der letzte Index als Müll betrachtet werden kann. Immer noch verwirrender Code und Zustand. Die Verwendung von [null] ist nicht OK, da wir einen untergeordneten Status 'null' haben könnten.

Wer kann das auf eine gute Weise lösen? Kann dies nicht unterstützt werden, da nach #combineAll keine andere Darstellung eines leeren Arrays vorhanden sein sollte?

+0

Dies wurde in https://github.com/ReactiveX/rxjs/issues/1910 behoben. –

Antwort

0

Credits gehen auf Github Benutzer trxcllnt, die die folgende Antwort gegeben:

combineAll nicht emittieren, es sei denn die vereinigten Observable mindestens einen Wert emittieren, aber man konnte die Sammlung, um sicherzustellen, überprüfen Sie‘ re Kombination leer ist oder nicht, und entweder kombiniert oder ein leeres Array emittieren:

var arrayOfStreamsStream = Rx.Observable .of( [], [ Rx.Observable.of('blah-1'), // component state. Rx.Observable.of('blah-2'), Rx.Observable.of('blah-3') ], [], [ Rx.Observable.of('foo-1'), Rx.Observable.of('qux-2') ] ) .switchMap(function onMap(coll) { return coll.length === 0 ? Observable.of(coll) : Observable.combineLatest(...coll); }) .subscribe(function onSubscribe(data) { console.log('onSubscribe START') console.dir(data) console.log('onSubscribe END') })

2

Dies hat nichts mit combineAll zu tun. Das Problem ist, dass Observable.from nichts ergibt (eine leere Observable), wenn ein leeres Array übergeben wird.

Die einzige brauchbare Lösung, die ich mir vorstellen kann, wenn Sie ein Ergebnis von einem leeren Array erhalten müssen, ist, in diesem Fall etwas anderes zurückzugeben.

Ann Beispiel zur Veranschaulichung des Problems und eine mögliche Lösung.

var data = [1, 2, 3, 4, 5]; 

log('With data: '); 
Rx.Observable.from(data) 
    .subscribe(function (d) { log('data: ' + d); }); 

// Prints: 
// With data: 
// data: 1 
// data: 2 
// data: 3 
// data: 4 
// data: 5 

var data = []; 

log('Without data: '); 
var nullDataObject = { msg: 'my null data object' }; 
Rx.Observable.from(data.length == 0 ? [nullDataObject] : data) 
    .subscribe(function (d) { log('data: ' + d); }); 

// Prints: 
// With data: 
// data: [object Object] 

Durchführbares Beispiel für jsfiddle.

Wenn Sie dies konsumieren, filtern Sie das Objekt, das ein leeres Array darstellt, einfach weg.

+0

Danke für die Rückmeldung! Es ist sehr wahr, dass es nie mit einem leeren Array als Eingabe arbeiten würde. Eine bessere Lösung (und akzeptierte Antwort) bestand darin, den Befehl combineAll/combineLatest vollständig mit einem ternären Selektor zu umgehen und nur ein Observable.of ([]) zurückzugeben, wenn die Länge === 0 ist. –