首页 > 解决方案 > 如何嵌套多个 Observables/Subscriptions

问题描述

1.问题

我正在尝试为我的博客创建一个不断变化的语言流程,总而言之,这就是它的样子:

  1. 用户单击触发事件(Subject)的按钮,即语言更改。
  2. 此语言更改用于Firebase根据该语言查询正确的页面。

如果我分别执行每个步骤,然后用户更改语言,则不会触发查询,因为它不知道刚刚发生的事件。所以我相信这应该是某种嵌套订阅/可观察的。我错了吗?

2. 到目前为止我的代码

我试过嵌套订阅,但没有用。我相信这是因为范围界定错误。现在,这就是我正在尝试的:

this.headerService.langChanged.pipe(
  map(
    (newLang: string) => {
      this.db
        .collection<AboutMePage>(
          this.aboutMeCollectionName, 
          ref => ref.where('lang', '==', newLang)
        )
        .valueChanges();
  })
)
  .subscribe(
    value => {
      this.aboutMe = value[0]
    }
  );

headerService.langChanged一个Subject<string>

rxjs这个用例有操作员吗?concat似乎是一个不错的候选人,但它会等待前一个Observable结束,在这种情况下它不会。还有一个事实是我必须将参数传递给下一个可观察的......

标签: angulartypescriptfirebaserxjs

解决方案


我认为使用 , , , 等中的任何一个都可以为您提供有效的解决方案concatswitchMapmerge实际上forkJoin取决于您想要从中获得的小东西,例如并发性。我在这里使用了一个小 Stackblitz 示例forkJoinhttps ://stackblitz.com/edit/angular-xyf8a6

您可以在控制台日志中看到每个内部的不同时间,Observable以验证 usingforkJoin有它,这样它只需要最慢的 observable 时间。

和我拥有的订阅:

this.langChanged
  .subscribe(newLang => {
    console.log(`language changed ${newLang}`);
    this.cancelLangChange.next();
    forkJoin(
      this.getUserName(newLang), 
      this.getUserBio(newLang), 
      this.getUserCreationDate(newLang)
    )
      .pipe(takeUntil(this.cancelLangChange))
      .subscribe(([username, bio, userCreationDate]) => {
        this.aboutMe.username = username;
        this.aboutMe.bio = bio;
        this.aboutMe.userCreationDate = userCreationDate;
      });
  });

我还添加了第二个,这意味着如果用户在加载第一个更改时选择了另一种语言,则Subject cancelLangChange取消订阅。forkJoin


推荐阅读