Daniel Caldera
Daniel Caldera

Reputation: 1119

Rxjs: Merge two streams with one stream that depends of another

I have a stream that calls a service that returns a stream that needs the info of the original stream for the request.

this.messages$ = this.selectedChat$
.switchMap(chat => this.chatService.subscribeMessages(chat.room))
.map(messages) =>
  messages.map((message: any) => {
    //Here need add information of the chat object
    return message;
  })
);

All operators that I see that can merge the streams and separate them later (like combineLatest) receive parameters, therefore, I can´t use the original stream info to call the service that generates the other stream, and I would not like to use subscribe on the original stream and return a new stream inside the subscribe because it's a little messy code.

Any advice?

Upvotes: 7

Views: 6711

Answers (3)

Richard Matsen
Richard Matsen

Reputation: 23533

I know this question has been answered, but I'm curious - looks to me like a mix-up with the brackets and a missing return.

Original:

this.messages$ = this.selectedChat$
.switchMap(chat => this.chatService.subscribeMessages(chat.room))
.map(messages) =>
  messages.map((message: any) => {
    //Here need add information of the chat object
    return message;
  })
);

This looks like a typo .map(messages) =>.

I tried this

const selectedChat$ = Observable.of({ room: '1', chatter: 'me', chattee: 'you' })
const subscribeMessages = (room) => Observable.of(['msg1', 'msg2'])

const messages$ = selectedChat$
  .switchMap(chat => subscribeMessages(chat.room)
    .map(messages => {
      return messages.map(message => {
        //Here need add information of the chat object
        return [message, chat];
      })
    })
  )

messages$.subscribe(console.log)

and got a result with chat in it, after proper closure is applied.

Do I have the wrong shape for test observables, or misunderstood the requirement?

Upvotes: 2

Jota.Toledo
Jota.Toledo

Reputation: 28454

Use the selector function in the switchMap operation:

this.messages$ = this.selectedChat$
.switchMap(chat => this.chatService.subscribeMessages(chat.room), 
(chat,messages)=>({chat,messages})) // create a new object, using the inner observable and the mapped one
.map(data =>
  data.messages.map((message: any) => {
    // Here data.chat has the chat information
    return message;
  })
);

For more information about the switchMap operator check here

Upvotes: 7

Fan Cheung
Fan Cheung

Reputation: 11380

Something like that?

this.messages$ = this.selectedChat$
.switchMap(chat => {
// chat still within the scope
  return this.chatService.subscribeMessages(chat.room))
    .map(messages) =>
       messages.map((message: any) => {
       //Here need add information of the chat object
       return message;
     })
});

if you insist on passing down the variable you can try

this.messages$ = this.selectedChat$
.switchMap(chat =>this.chatService.subscribeMessages(chat.room).combineLatest(Observable.of(chat)))
    .map([messages,chat]) =>
       messages.map((message: any) => {
       //Here need add information of the chat object
       return message;
     })
});

You can also setup a global variable store with use of Behaviour subject, if there are too many global value needed

Upvotes: 1

Related Questions