Javascript 如何在完成两个Angular 2订阅后调用函数?
我在Angular 2.3.1上,我对Angular和基于事件的编程都相当陌生。我有两个订阅,Javascript 如何在完成两个Angular 2订阅后调用函数?,javascript,angular,rxjs,Javascript,Angular,Rxjs,我在Angular 2.3.1上,我对Angular和基于事件的编程都相当陌生。我有两个订阅,route.params.subscribe和engineService.getEngines()。在我的onInit中,我想在this.route.params.subscribe和this.engineService.getEngines()之后调用getEngineName 原因:getEngineName函数取决于queryParams中的engineId和engines数组,该数组在getEn
route.params.subscribe
和engineService.getEngines()
。在我的onInit
中,我想在this.route.params.subscribe
和this.engineService.getEngines()之后调用getEngineName
原因:getEngineName
函数取决于queryParams中的engineId
和engines
数组,该数组在getEngines()调用完成后填充
我确实看过flatMap
和switchMap
,但我没有完全理解它们
这是组件中的代码:
导出类ItemListComponent实现OnInit{
项目:项目[];
发动机:发动机[];
私有引擎ID:编号;
建造师(
专用路由器:路由器,
专用路由:激活的路由,
私人项目服务:项目服务,
专用引擎服务:引擎服务
) {}
恩戈尼尼特(){
this.route.params.subscribe((params:params)=>{
this.engineId=+params['engineId'];
//itemService与此问题无关
this.itemService.getItems({engineId:this.engineId})
.订阅((项目:项目[])=>{
这个项目=项目;
});
});
this.engineService.getEngines()
.subscribe(engines=>this.engines=engines);
//这应仅在填充engineId和engines阵列后运行。
this.getEngineName(this.engineId);
}
getEngineName(engineId:number){
this.engines.find((engine)=>{
返回engine.id==engineId;
})
}
}
为什么不将逻辑移到route.params
回调中
this.route.params.subscribe((params: Params) => {
this.engineId = +params['engineId'];
// itemService is irrelevant to this question
this.itemService.getItems({engineId: this.engineId})
.subscribe((items: Item[]) => {
this.items = items;
});
//this.engineId is defined here (1)
this.engineService.getEngines()
.subscribe((engines) => {
this.engines = engines;
//this.engines is defined here (2)
this.getEngineName(this.engineId);
});
});
使用flatMap
和forkJoin
:
this.route.params.flatMap((params: Params) => {
this.engineId = +params['engineId'];
return Observable.forkJoin(
this.itemService.getItems({engineId: this.engineId}),
this.engineService.getEngines()
)
}).subscribe((data)=>{
let items = data[0];
let engines = data[1];
this.items = items;
this.engines = engines;
this.getEngineName(this.engineId);
});
switchMap
建议在此场景中使用
this.route.params.pluck('engineId') //pluck will select engineId key from params
.switchMap(engineId => {
this.getItems(engineId);
return this.engineService.getEngines().map(engines => {
/*this.engineService.getEngines() emits the list of engines.
Then use map operator to convert the list of engines to engine we are looking for
*/
return engines.find((engine) => {
return engine.id === engineId;
})
})
}).subscribe(engine => {
//engine
})
getItems(engineId) {
this.itemService.getItems({engineId: engineId})
.subscribe((items: Item[]) => {
this.items = items;
});
}
假设参数中的engineId发生变化,第一个可观察的this.route.params.pulk('engineId')
将发出数据,这将导致下一个可观察的this.engineService.getEngines()
被触发。现在假设路径在这个可观测对象发出数据之前发生了变化。这里您需要取消getEngines
observable以防止错误。这是通过switchMap
完成的
switchMap
如果触发外部可观测,则取消内部可观测
注:我避免保留任何类似于this.engineId
等的状态。您可以使用CombineTest。您的问题与此类似:使用CombineTest,您不需要嵌套订阅。啊!对这很有道理!谢谢。这对我来说是成功的。@Yathi很高兴我能帮上忙,只是想知道,因为我对它不太了解:rxjs中的嵌套订阅行吗?我个人尽量避免使用它们,因为我认为代码更容易阅读,但可能是我弄错了。@chrigu我用flatMap
+forkJoin
更新了我的答案,我可能在某个地方弄错了,所以一定要检查返回参数(data
)。希望有帮助;)@echonax我承认我必须查看forkJoin
up:)。如果分叉流终止,这应该可以工作。我不完全遵循这一点。您能在代码中添加更多注释以使其更清楚吗?另外,我在哪里调用我的itemService.getItems()
?我假设它在switchMap中的return语句之前。为什么这比第一个答案更好?