Frigo
Frigo

Reputation: 314

Merging Observables of different types

Scenario: I have an Angular service that exposes an object that will change over time, let's call it User. A User has some properties that will also change over time, let's call it Friends.

The User and Friends may be fetched from the server at times, and I would like to merge this information into a single User observable.

Essentially, this:

interface User {
  name: string;
  friends: Friend[];
}

class MyService {
  private userSubject = new Subject<User>();
  private newFriendSubject = new Subject<Friend>();

  user: Observable<User>; // Consumers will subscribe to this

  constructor() {
    // Here, user should be set up to merge the two subjects
    this.user = ...
  }

  fetchUser() {
    fetchUserFromServer().subscribe(user => this.userSubject.next(user))
  }

  addFriend(f: Friend) {
    addFriendServerRequest(f).subscribe(newFriend => this.newFriendSubject.next(newFriend))
}

Now, I would like to combine values from the User subject, with ones from the Friends subject, so that they represent a User with Friends.

Question: How do I do this? I'm thinking I should use some combination of merge and scan:

this.user = merge(this.userSubject, this.newFriendSubject).pipe(
  scan((user, userOrFriend) => {
    if (userOrFriend is User) return userOrFriend
    else return {...user, friends: [...user.friends, userOrFriend]}
  })
)

...But this doesn't really work, because scan needs the accumulator (user) and the value (userOrFriend) to be of the same type. Am I going at this the wrong way, or is there some operator/pattern I'm missing?

Kind of a generic question, but I could really use some help from somebody with some rxjs expertise.

Upvotes: 0

Views: 4572

Answers (2)

To conform to latest documentation.

const u = combineLatest(this.userSubject, this.newFriendSubject);
u.subscribe(([user, friends]) => {
    this.user = ...
});

Upvotes: 0

Eduardo Vargas
Eduardo Vargas

Reputation: 9392

You can use the combineLatest operator

this.user =   combineLatest(this.userSubject, this.newFriendSubject)
  subscribe(([user, friends]) => {
    //do something here
  })

Upvotes: 1

Related Questions