合并 4 个可观察到的条件

Merging 4 observable with conditions

我需要创建一个 Observable 来收集来自某些 http 请求的其他 observable。新的可观察对象必须是相同对象类型的集合,但每个项目都必须是唯一的。你能帮我写出正确的方法来实现这个目标吗?

// 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();
}

所以约束是:

  1. 如果用户未登录,则集合必须按以下顺序排列:defaultTopic、topTopic
  2. 如果用户登录集合必须在此order:defaultTopic、topTopic、userTopic
  3. 如果用户已登录,我将读取过滤默认主题的 UserSettings$(如果它们将被隐藏或显示)
  4. 主题必须是唯一的(重复的主题只会在默认和用户主题可见)

我尝试使用 combineLatest 和 forkJoin,但我不知道如何将运算符与身份验证观察器区分开来。

我非常感谢一些提示! 谢谢

你可以尝试这样的事情。当然,既然你的问题不完整,这个答案也不完整。

您必须自己实现一些部分。尽管如此,以下应该是开始修补的好地方。

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
            )
          )
        ))
      );

    })
  );

}