getBudgetMap(budgetMonthID){
this.rows = [];
this.categoryService.getCategory(budgetMonthID).subscribe(category =>{
this.categoryList = category;
this.categoryList.forEach(category => {
this.transactionService.getTransaction(budgetMonthID, category.id).subscribe(transaction => {
this.rows = this.rows.concat(transaction);
})
})
)
}
为简单起见,我有一个嵌套的ajax服务(http.get)调用,第一个(getCategory)
返回一个基于budgetMonthID
的类别列表。类别的数量各不相同。然后,每个类别将进行第二次调用getTransaction
,以检索属于每个类别的所有交易。上面的代码工作正常,但是我一直在阅读有关 Angular 的map
,flapMap
,pipe
的信息,我只是想不出如何更改它讨厌的代码。谢谢
答案 0 :(得分:1)
您可以使用
rxjs operators
来处理异步调用。要珍贵,您应该使用switchmap
或flatmap
或mergemap
。可以给代码,但是以后您将再次遇到相同的问题。因此,我鼓励您有时要花些时间来了解rxjs运算符的工作原理。
请逐步浏览-https://www.learnrxjs.io/operators/transformation/switchmap.html
答案 1 :(得分:1)
这确实需要一些rxjs知识。
this.categoryService.getCategory(budgetMonthID).pipe(
tap((categories) => this.categoryList = categories),
mergeMap((categories) => zip(
...categories.map(
(category) => this.transactionService.getTransaction(budgetMonthID, category.id)
)
)
).subscribe((rows) => {
this.rows = rows;
});
首先,我们使用tap将类别保存到categoryList
中。这是一个仅执行功能但对管道流量没有影响的运算符。
此后,我们使用mergeMap拾取类别,并返回另一个Observable。在这种情况下,zip
将等待所有参数完成,然后以数组形式发出,并由订阅者拾取。
您还可以尝试从角度看内置async
管道。这消除了取消订阅组件内部的需要,并保持了组件的清洁。这会将您的代码更改为此:
this.categoryList$ = this.categoryService.getCategory(budgetMonthID).pipe(
shareReplay(1)
);
this.rows$ = this.categoryList$.pipe(
mergeMap((categories) => zip(
...categories.map(
(category) => this.transactionService.getTransaction(budgetMonthID, category.id)
)
)
);
您可以在模板中像这样访问它:
<div *ngFor="let category of categoryList$ | async"></div>
<div *ngFor="let row of rows$ | async"></div>