【问题标题】:Javascript: Combine Multiple Subscription Result into One ArrayJavascript:将多个订阅结果合并为一个数组
【发布时间】:2021-10-11 12:18:35
【问题描述】:

我正在尝试从一个订阅中获取数据,并且基于数据,我正在调用嵌套订阅以添加到数据对象中。这就是我的函数的样子:

this.subCatSubscription = this.afDatabase.list('/sub-categories/').snapshotChanges().subscribe((subCat: any) => {
      this.categories = [];
      subCat.forEach( sc => {
        if(sc.payload.val().category) {
          this.cat1Subscription = this.afDatabase.list('/categories/').snapshotChanges().subscribe((cat: any) => {
            cat.forEach(c => {
              if(c.key === sc.payload.val().category) {
                this.categories.push({ key: sc.key, ...sc.payload.val(), parentCatName: c.payload.val().name });
                //this.categories.sort((a, b) => a.name.localeCompare(b.name));
              }
            });
          });
        } else {
          this.categories.push({ key: sc.key, ...sc.payload.val() });
          //this.categories.sort((a, b) => a.name.localeCompare(b.name));
        }
        console.log(this.categories)
      });
    })

有没有什么办法可以把上面的两个订阅结合起来,根据我的条件得到想要的数据?

谢谢。

【问题讨论】:

  • 每当我看到 forEach 时,我都会想到 forkJoin 运算符。

标签: javascript firebase rxjs subscription


【解决方案1】:

当您从示例中删除 observables 时,您要做的是创建一个对象数组,而其中一些对象是从第二个数组中发生变异的。我提供的是以下步骤。

  1. 获取子类别数据。
  2. 创建默认对象数组。
  3. 获取父类数据。
  4. 对于每个包含父匹配的子类别,改变对象。否则,按原样返回对象。

对于第 3 步(获取父类别数据),我们可以使用简单的 switchMap() 来完成此操作。

  this.categories$ = this.afDatabase
    .list("/sub-categories")
    .snapshotChanges()
    .pipe(
        map(subCategories=>
            subCategories.map(sc=>({ key: sc.key, ...sc.payload.val() }))
        ),
        switchMap(categories=>this.afDatabase
            .list("/categories/")
            .snapshotChanges()
            .pipe(
                map(parent=>
                    categories.map(c=>{
                        const match = parent.find(pc=>pc.key === c.category);
                        return !!match ? {...c, parentCatName: match.payload.val().name} : c
                    })
                )
            )
        )
    );

现在,我们只请求一次/categores/,而不是每次匹配多次。

【讨论】:

    【解决方案2】:

    我会为此使用 switchMap,因为第二个 DB 调用取决于第一个。 因此,如果第二个请求未决并且第一个 obervable 再次发出,我们可以使用取消效果。

    请记住,嵌套订阅被视为一种反模式。您可能希望使用 mergeMap/flatMap 或 switchMap 来实现相同的效果。

    我会建议这样的事情:

    this.subCatSubscription = this.afDatabase.list('/sub-categories/').snapshotChanges()
    .pipe(
      switchMap(subCat => {
        this.categories = [];
        return subCat.forEach( sc => {
          return sc.payload.val().category ? this.afDatabase.list('/categories/').snapshotChanges() : empty()
        });
      })
    ).subscribe(console.log)
    

    可能这段代码并不完美(不确定我们是否需要双重返回),我现在无法测试它,但我希望它有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-22
      相关资源
      最近更新 更多