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:
- If user is not logged collection must be in this order: defaultTopic, topTopic
- If user is logged collection must be in this order:defaultTopic, topTopic, userTopic
- If user is logged I will read the UserSettings$ that filter the defaultTopics if they will be hidden or shown
- 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
)
)
))
);
})
);
}