angulartypescriptrxjsobservablecombinelatest

Angular - Observables combined result multiple calls


EDIT 30-07-2018 01:57 CET: Still looking for a solution to the problem below:

I have the following code:

getBoolean(dataRef1, dataRef2) {
  const myFirstObservable = this.af.object(dataRef1).valueChanges();
  const mySecondObservable = this.af.object(dataRef2).valueChanges();

  return combineLatest(myFirstObservable, mySecondObservable).pipe(map(([data1, data2]) => data1 && data2)))
}

Basically what the code does is: it combines the results of the two observables and then checks each whether it has returned any value. If both observables have a value, return true else return false.

So far so good, everything is working as expected. I then call the method from my View, provide dynamic node references for the observables, and use the boolean to add a conditional element:

<div *ngIf="getBoolean('dataN', 'dataK') | async"> My lovely div content goes here</div>

However, my div does not display on my view at all.

Can someone tell me where I am wrong and help me achieve my desired result?


Solution

  • Most likely the problem is that you're calling a getBoolean('dataN', 'dataK') method in your template. On every change detection Angular invokes getBoolean method that returns a new Observable. The old one is unsubscribed by async and only the new one is active.

    At the same time combineLatest operator requires all source Observables to emit at least once which is not very likely to happen because async subscribes/unsubscribes on ever change detection cycle that can happen eve multiple times a second.

    So I'd recommend you to store the Observable in a property:

    public obs$ = combineLatest(myFirstObservable, mySecondObservable, (data1, data2) => data1 && data2);
    

    Then only use obs$ | async in templates.

    Eventually, you can add some logic inside getBoolean that checks whether obs$ exists and if it does you'll just return it as is.