Javascript: 将多个订阅结果组合成一个数组

Javascript: Combine Multiple Subscription Result into One Array

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

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

有什么方法可以结合上面的两个订阅,根据我的条件得到想要的数据吗?

谢谢。

我会为此使用 switchMap,因为第二个数据库调用取决于第一个。 所以如果第二个请求挂起并且第一个 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)

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

当您从您的示例中删除可观察对象时,您试图做的是创建一个对象数组,而其中一些对象是从第二个数组变异而来的。我提供的是以下步骤。

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

对于第 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/ 一次,而不是每次匹配多次。