如何在 Angular RxJS 中正确链接 concatMap
How to properly chain concatMaps in Angular RxJS
this.route.params.pipe(
concatMap((param) => {
const ein = param['nonprofit-id'];
return this.nonprofitService.getNonprofit(ein).pipe(
concatMap((nonprofit) => {
this.nonprofit = nonprofit;
const ratingID = nonprofit.currentRating?.ratingID ? nonprofit.currentRating.ratingID : -1;
return this.nonprofitService.getRatingForNonprofit(ein, ratingID).pipe(
concatMap((nonprofitRating) => {
this.nonprofitRating = nonprofitRating;
const causeID = this.nonprofit?.cause?.causeID ? this.nonprofit?.cause?.causeID : 0;
return this.nonprofitService.getSimilarNonprofits(causeID);
})
);
})
);
})
).subscribe((response) => {
this.similarNonprofits = response;
});
我想知道以上是否是在 Angular RxJS 中链接 concatMap 的正确方法。其他两个调用依赖于检索到的相关“非营利组织”,以便返回其对象。 Rating 和 Similar Nonprofits 可以同时检索,所以我想有一些方法可以做到这一点,而无需将这些 concatMap 相互嵌套。
如果你需要使用所有以前的值,它通常以嵌套越来越多的链结束,但在这种情况下它似乎已经太复杂了所以你可以 map()
每个内部 Observable 到一个数组(或对象)中) 如下所示:
this.route.params.pipe(
concatMap((param) => {
const ein = param['nonprofit-id'];
return this.nonprofitService.getNonprofit(ein).pipe(
map(nonprofit => [ein, nonprofit]),
);
),
concatMap(([ein, nonprofit]) => {
const ratingID = ...;
this.nonprofitService.getRatingForNonprofit(ein, ratingID).pipe(
map(nonprofitRating => [nonprofitRating, ein, nonprofit]),
);
}),
concatMap(([nonprofitRating, ein, nonprofit]) => {
const causeID = ...;
return this.nonprofitService.getSimilarNonprofits(causeID).pipe(
map(similar => [similar, nonprofitRating, ein, nonprofit]),
);
}
).subscribe(([similar, nonprofitRating, ein, nonprofit]) => { ... });
显然,您不必解包作为参数传递给连续 concatMap
的每个数组,但我希望您能明白这一点。
继续@martin 的回答,我建议使用 forkJoin
将最后两个 concatMap
合并为一个请求,因为它们不相互依赖。这也将并行触发请求,并可能有助于提高性能(虽然微不足道)。
我还用 nullish coalescing operator ??
替换了三元运算符。
this.route.params.pipe(
concatMap((param: any) => {
const ein = param['nonprofit-id'];
return this.nonprofitService.getNonprofit(ein).pipe(
map((nonprofit) => ([ein, nonprofit]))
);
}),
concatMap(([ein, nonprofit]) =>
forkJoin([
this.nonprofitService.getRatingForNonprofit(ein, (nonprofit.currentRating?.ratingID ?? -1)),
this.nonprofitService.getSimilarNonprofits(ein, (this.nonprofit?.cause?.causeID ?? 0))
]).pipe(
map(([nonprofitRating, similarNonprofits]) => ([
nonprofit,
nonprofitRating,
similarNonprofits
]))
)
)
).subscribe({
next: ([nonprofit, nonprofitRating, similarNonprofits]) => {
this.nonprofit = nonprofit;
this.nonprofitRating = nonprofitRating;
this.similarNonprofits = similarNonprofits;
},
error: (error: any) => {
// handle error
}
});
您还可以定义一个具有属性的对象,以避免对多个元素使用解构语法。
this.route.params.pipe(
concatMap((param) => {
const ein = param['nonprofit-id'];
return this.nonprofitService.getNonprofit(ein).pipe(
concatMap((nonprofit) => {
this.nonprofit = nonprofit;
const ratingID = nonprofit.currentRating?.ratingID ? nonprofit.currentRating.ratingID : -1;
return this.nonprofitService.getRatingForNonprofit(ein, ratingID).pipe(
concatMap((nonprofitRating) => {
this.nonprofitRating = nonprofitRating;
const causeID = this.nonprofit?.cause?.causeID ? this.nonprofit?.cause?.causeID : 0;
return this.nonprofitService.getSimilarNonprofits(causeID);
})
);
})
);
})
).subscribe((response) => {
this.similarNonprofits = response;
});
我想知道以上是否是在 Angular RxJS 中链接 concatMap 的正确方法。其他两个调用依赖于检索到的相关“非营利组织”,以便返回其对象。 Rating 和 Similar Nonprofits 可以同时检索,所以我想有一些方法可以做到这一点,而无需将这些 concatMap 相互嵌套。
如果你需要使用所有以前的值,它通常以嵌套越来越多的链结束,但在这种情况下它似乎已经太复杂了所以你可以 map()
每个内部 Observable 到一个数组(或对象)中) 如下所示:
this.route.params.pipe(
concatMap((param) => {
const ein = param['nonprofit-id'];
return this.nonprofitService.getNonprofit(ein).pipe(
map(nonprofit => [ein, nonprofit]),
);
),
concatMap(([ein, nonprofit]) => {
const ratingID = ...;
this.nonprofitService.getRatingForNonprofit(ein, ratingID).pipe(
map(nonprofitRating => [nonprofitRating, ein, nonprofit]),
);
}),
concatMap(([nonprofitRating, ein, nonprofit]) => {
const causeID = ...;
return this.nonprofitService.getSimilarNonprofits(causeID).pipe(
map(similar => [similar, nonprofitRating, ein, nonprofit]),
);
}
).subscribe(([similar, nonprofitRating, ein, nonprofit]) => { ... });
显然,您不必解包作为参数传递给连续 concatMap
的每个数组,但我希望您能明白这一点。
继续@martin 的回答,我建议使用 forkJoin
将最后两个 concatMap
合并为一个请求,因为它们不相互依赖。这也将并行触发请求,并可能有助于提高性能(虽然微不足道)。
我还用 nullish coalescing operator ??
替换了三元运算符。
this.route.params.pipe(
concatMap((param: any) => {
const ein = param['nonprofit-id'];
return this.nonprofitService.getNonprofit(ein).pipe(
map((nonprofit) => ([ein, nonprofit]))
);
}),
concatMap(([ein, nonprofit]) =>
forkJoin([
this.nonprofitService.getRatingForNonprofit(ein, (nonprofit.currentRating?.ratingID ?? -1)),
this.nonprofitService.getSimilarNonprofits(ein, (this.nonprofit?.cause?.causeID ?? 0))
]).pipe(
map(([nonprofitRating, similarNonprofits]) => ([
nonprofit,
nonprofitRating,
similarNonprofits
]))
)
)
).subscribe({
next: ([nonprofit, nonprofitRating, similarNonprofits]) => {
this.nonprofit = nonprofit;
this.nonprofitRating = nonprofitRating;
this.similarNonprofits = similarNonprofits;
},
error: (error: any) => {
// handle error
}
});
您还可以定义一个具有属性的对象,以避免对多个元素使用解构语法。