Home > Net >  Merging 4 observable with conditions
Merging 4 observable with conditions

Time:03-02

I need to create an Observable that will collect other observables coming from some http requests. The new observable must be a collection of same object type but every item must be unique. Can you help me writing the correct method to achieve this goal?

// The result observable that I need
topicCollection$ = BehaviorSubject<Topic[]> = new BehaviorSubject<Topic[]>(null);

// Boolean observable of authentication
isAuthenticated: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(null);

// Return default topic
get defaultTopics$(): Observable<Topic[]>{
   return this.defaultTopic.asObservable();
}

// Return topics selected by Admin
get TopTopics$(): Observable<Topic[]>{
  return this.topTopic.asObservable();
}

//Return topics selected by User
get userTopics$: Observable<Topic[]>{
   return this.userTopic.asObservable();
}

//Return user settings 
get userSettings$(): Observable<any[]>{
  return this.userSettings.asObservable();
}

So the constraint are:

  1. If user is not logged collection must be in this order: defaultTopic, topTopic
  2. If user is logged collection must be in this order:defaultTopic, topTopic, userTopic
  3. If user is logged I will read the UserSettings$ that filter the defaultTopics if they will be hidden or shown
  4. Topic must be unique (duplicate topics would be only in default and user topic observable)

I try with combineLatest and forkJoin but I don't know how to differenziate the operators with the authentication observer.

I really appreciate some tips! Thanks

CodePudding user response:

You can try something like this. Of course since your question isn't complete, neither is this answer.

You'll have to implement a few parts yourself. Still, the following should be a decent place to start tinkering.

get topicCollection$(): Observable<Topic[]> {

  return this.isAuthenticated.pipe(
    take(1),
    switchMap(isLogged => {

      // The easy part, merge arrays emitted from two separate streams
      const mergeDefaultTop$ = forkJoin([
        this.defaultTopics$.pipe(take(1)),
        this.topTopics$.pipe(take(1))
      ]).pipe(
        map((v: Topic[][]) => v.flat())
      );

      // If the user is logged in, merge then filter the merged topics.
      return !isLogged ? mergeDefaultTop$ : mergeDefaultTop$.pipe(
        switchMap(topics => this.userTopics$.pipe(
          map(userTopics => [...topics, ...userTopics])
        )),
        switchMap(topics => this.userSettings$.pipe(
          map(settings => topics
            // You'll want to update this filter. I can't define it for you 
            // as I dont know what a topic is/ how it's labled, etc.
            .filter(topic => topic !in settings)
            // Filter to remove duplicats. You may want to better define
            // equality depending on your use case (again, I can't do
            // that for you with what you've provided)
            .filter((value, index, self) =>
              self.indexOf(value) === index
            )
          )
        ))
      );

    })
  );

}
  • Related