我认为这是一个更rxjs
相关的问题,但我在Angular App中面对它。
我们在我们的应用程序中嵌套了路由器事件的订阅。
我将尝试逐步解释代码的工作原理。
我们有一个带有合同列表的DropDown。 我们有一个带有年份列表的DropDown。
一旦用户更改了DropDown合同中的选择,我们需要导航并将合同ID放入带有所选合同ID的URL中,然后我们必须加载与此合同ID相关的年份,我们订阅路由器事件:
this.activatedRoute.parent.paramMap
.map(m => +m.get("contractId"))
.distinctUntilChanged()
.subscribe(contractId => {
// CALL SERVICE TO LOAD DROPDOWN WITH YEARS
})
用户还可以更改DropDown年份中的年份。
一旦用户更改DropDown年份中的选择,我们还必须导航并更新所选年份的URL,然后我们需要加载一个包含数据的网格,这就是它的外观:
this.activatedRoute.parent.paramMap
.map(m => +m.get("contractId"))
.distinctUntilChanged()
.subscribe(contractId => {
// CALL SERVICE TO LOAD DROPDOWN WITH YEARS
this.activatedRoute.queryParamMap
.map(m => +m.get("year"))
.distinctUntilChanged()
.subscribe(year => {
// CALL SERVICE TO LOAD GRID WITH DATA
})
});
这里的问题是每次合同ID发生变化时,我都会创建this.activatedRoute.queryParamMap
的新订阅,这意味着会有几个重复的http请求。
我也尝试使用unsubscribe
但是当选择发生变化时,带有年份的DropDown将不再触发订阅。
解决此类嵌套调用的最佳方法是什么?
修改:
我修好了 - 不是那么优雅的IMO:
let subscription = new Subscription();
this.activatedRoute.parent.paramMap
.map(m => +m.get("contractId"))
.distinctUntilChanged()
.subscribe(contractId => {
subscription.unsubscribe();
// CALL SERVICE TO LOAD DROPDOWN WITH YEARS
subscription = this.activatedRoute.queryParamMap
.map(m => +m.get("year"))
.distinctUntilChanged()
.subscribe(year => {
// CALL SERVICE TO LOAD GRID WITH DATA
})
});
也许rxjs
提供了更优雅的解决方法?
修改
我创建了一个plunker来说明这个场景:
答案 0 :(得分:1)
解决方案是使用switchMap
而不是几个subscribers
,我们在这里:
this.activatedRoute.parent.paramMap
.map(m => +m.get("contractId"))
.distinctUntilChanged()
.switchMap(contractId => {
// CALL SERVICE TO LOAD DROPDOWN WITH YEARS
return this.activatedRoute.queryParamMap
.map(m => +m.get("year"))
.distinctUntilChanged()
.switchMap(year => {
// CALL SERVICE TO LOAD GRID WITH DATA
})
}).subscribe(() => {});
答案 1 :(得分:0)
好的,我花了一些时间与Plunker。我更新了ngOnInit,如下所示:
ngOnInit() {
let contractId;
let year;
this.activatedRoute.parent.paramMap
.subscribe(params => {
this.contractId = params.get('contractId');
console.log("Selected contract Id: " + this.contractId);
// Code to populate the years from the contractid
})
this.activatedRoute.queryParamMap
.subscribe(params => {
this.year = params.get('year');
console.log("Selected year: " + this.year)
if (this.year) {
this.loadGrid(this.contractId, this.year);
} else {
// Clear grid??
}
});
}
第一个订阅会监视合同的变更并获得新的一年。
第二个订阅监视年度查询参数的更改并重新加载网格。
我不认为你想要一个,因为这会增加多个订阅。
这是你想要达到的目标吗?
更新了plunker:https://plnkr.co/edit/7Pn6HX3D6fZ8iHdylbUW?p=preview