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),我现在无法测试它,但我希望它能有所帮助。
当您从您的示例中删除可观察对象时,您试图做的是创建一个对象数组,而其中一些对象是从第二个数组变异而来的。我提供的是以下步骤。
- 获取子类数据。
- 创建默认对象数组。
- 获取父类别数据。
- 对于包含父匹配项的每个子类别,改变对象。否则,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/
一次,而不是每次匹配多次。
我正在尝试从一个订阅中获取数据,并根据数据调用嵌套订阅以将其添加到数据对象中。这是我的函数的样子:
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),我现在无法测试它,但我希望它能有所帮助。
当您从您的示例中删除可观察对象时,您试图做的是创建一个对象数组,而其中一些对象是从第二个数组变异而来的。我提供的是以下步骤。
- 获取子类数据。
- 创建默认对象数组。
- 获取父类别数据。
- 对于包含父匹配项的每个子类别,改变对象。否则,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/
一次,而不是每次匹配多次。