Search code examples
observablerxjs5angular2-observables

Observable.zip but get first value, don't wait for all values


Say I have this:

const a = new BehaviorSubject(0);
const b = new BehaviorSubject(0);

Observable.zip(
    a.asObservable(),
    b.asObservable()
)
.subscribe(v => {
    // this will fire with [0,0]
    // but I want it to also fire with [1,0]
});

a.next(1);

how can I achieve what's in the comment in the subscribe next function? I believe I need to find a different operator than Observable.zip(), something like Observable.first().


Solution

  • .zip() will only work if the emissions from the observables are zippable. For your case, because 0,0 is already zipped, hence there will only be one such emission. If you want to have next emission, your b subject will have to emit a value too:

    const a = new BehaviorSubject(0);
    const b = new BehaviorSubject(0);
    
    Observable.zip(
        a.asObservable(),
        b.asObservable()
    )
        .subscribe(v => {
            // this will fire with [0,0]
            // will fire only if both a and b has emisions. 
            // this also logs [1,1] because there is a b.next(1)
        });
    
    a.next(1);
    b.next(1); // this step is crucial
    

    If you want to detect any changes of any number of Observables combined, you will have to use Observable.combineLatest().

    The CombineLatest operator behaves in a similar way to Zip, but while Zip emits items only when each of the zipped source Observables have emitted a previously unzipped item, CombineLatest emits an item whenever any of the source Observables emits an item (so long as each of the source Observables has emitted at least one item). When any of the source Observables emits an item, CombineLatest combines the most recently emitted items from each of the other source Observables, using a function you provide, and emits the return value from that function.