Search code examples
rxjsrxjs5reactive-extensions-js

combineAll does not emit on empty array


JSBIN Sample

I have a changeable set of child components (POJO object) that each have its own state stream. Each time a user triggers addChild/removeChild/clearChildren, a new set of children state streams is emitted with #switchMap. So far so good! (And so amazed by RxJS!)

With Rx.Observable.from(arrayOfStateStreams).combineAll() I get a good result as long as the arrayOfStateStreams isn't an empty array.

Since this is a partial state that is combined(Latest) on a higher level, I need to get an empty array emitted or the global state tree will contain old state data that is no longer true!

I can emit some reserved token like ['EMPTY-ARRAY-PLACEHOLDER-TOKEN'], but that's just weird. A better way would be to always append one last stream into the array so the last index can be considered trash. Still confusing code and state though. Using [null] is not OK, since we could have a child state of 'null'.

Anyone who can solve this in a good way? Can't this be supported since there should be no other representation of an empty array after #combineAll?


Solution

  • Credits go to github user trxcllnt who provided the following answer:

    combineAll won't emit unless the combined Observables emit at least one value, but you could check to ensure the collection you're combining is empty or not, and either combine or emit an empty Array:

     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')
        })