2
votes

I have two hot/warm observables one provides list of user roles definitions and the second list of users (under the hood these ReplaySubject(1) which works like BehaviorSubject without starting value).

To display users I need to ensure I have list of roles definitions. Also if list of roles changes or list of users changes I have to re-render list.

I'd like to user the power of rxjs and combine this two observables to get semantics I described. I experimented with number of operators like switchMap, mergeMap, faltMap, forkJoin and zip however I couldn't make it work.

The only way I could make it work is to use two subscription like this:

 this.userRoleStore.observable.subscribe((roles) => {
      this.roles = roles;
      if (this.users == null) {
        this.userStore.observable.subscribe(users => {
          this.users = users;
        })
      }
 });

This way I ensure I have roles before I try render users and it will update both users and roles whenever they change.

Most promising was zip operator however it won't fire when only one of observable changes. SwitchMap operator will fire only when first observables has new value (so I get updates only on user or user roles changes).

2

2 Answers

5
votes

It looks like you're looking for combineLatest that emits when any of the source Observables emit after each of them emitted at least one value (it has both static and operator variants).

So in your case it would look like this:

Observable.combineLatest(
    this.userRoleStore.observable,
    this.userStore.observable
  )
  .subscribe(([role, user]) => ...);

Maybe also have a look at withLatestFrom.

0
votes

You can also Create a Type Users

export class Users{

roles: Roles[];

}

Now you can use an Async pipe which will track the roles automatically.