Manuel RODRIGUEZ
Manuel RODRIGUEZ

Reputation: 2161

Cancel previous inner Observables when a new higher-order Observable is emitted

Consider the following code:

this.msgService.getUserChatList()
    .do( (list) => { 
      this.unread = false;
      console.log(list);
     } )
    .mergeMap( chats => Observable.from(chats) )
    .mergeMap( chat => this.msgService.getLastMessage(chat['id']).map( lastMessage => this.containsUnreadMessages(lastMessage, chat['lastPresence']) ) )
    .filter( state => state === true )
    .subscribe( (unread) => {
      this.unread = true;
      console.log('result ', res);
    } );

getUserChatList(): - emits an element each time one of the chat changes - an element is a raw array containing all chats meta-data - never completes

getLastMessage(): - is an Observable that never completes

In the second mergeMap I am calling the function getLastMessage(). I need to be observe this observable only until a new item is emitted by the getUserChatList() otherwise I would multiple observations on last message of the same chat.

Illustration :

  1. getUserChatList emits : [chatMetaA:{}, chatMetaB:{}]
  2. code go through getLastMessage and start to observe lastMessage of chatA and chatB
  3. one of the chat change so a new item is emitted by getUserChatList containing the new version of the meta-data of the chats: [chatMetaA:{}, chatMetaB:{}]
  4. code go through getLastMessage and start to observe lastMessage of chatA and chatB. So we now observe twice last message of chatA and chatB

And it will go on and on...

My question is, how could I cancel observation on getLastMessage() once a new item is emitted by getUserChatList()? I tried using switch but couldn't manage to make it work

Upvotes: 1

Views: 1256

Answers (1)

Manuel RODRIGUEZ
Manuel RODRIGUEZ

Reputation: 2161

Solution was indeed to use switchMap:

this.msgService.getUserChatList()
    .do( () => { this.unread = false } )
    .switchMap(
      chats => Observable.from(chats)
        .mergeMap( chat => this.msgService.getLastMessage(chat['id'])
        .map( lastMessage => this.containsUnreadMessages(lastMessage, chat['lastPresence']) ) )
    )
    .filter( state => state === true )
    .subscribe( (unread) => {
      this.unread = true;
      console.log('result ', res);
    } );

Upvotes: 2

Related Questions