Javascript 如何在完成两个Angular 2订阅后调用函数?

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

我在Angular 2.3.1上,我对Angular和基于事件的编程都相当陌生。我有两个订阅,
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语句之前。为什么这比第一个答案更好?