2017-01-09 77 views
2

我在Angular 2.3.1上,对于Angular和基于事件的编程我都很新。我有两个订阅,route.params.subscribeengineService.getEngines()。在我的onInit中,我想在完成this.route.params.subscribethis.engineService.getEngines().subscribe之后致电getEngineName如何在两个Angular 2订阅完成后调用一个函数?

之所以这样:getEngineName功能依赖于engineId从queryParams和engines阵列被getEngines()呼叫完成后填充。

我看过flatMapswitchMap但我没有完全理解它们。

这是组件的代码:

export class ItemListComponent implements OnInit { 
 
    items: Item[]; 
 

 
    engines: Engine[]; 
 
    private engineId: number; 
 

 
    constructor(
 
    private router: Router, 
 
    private route: ActivatedRoute, 
 
    private itemService: ItemService, 
 
    private engineService: EngineService 
 
    ) {} 
 

 
    ngOnInit() { 
 
    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.engineService.getEngines() 
 
     .subscribe(engines => this.engines = engines); 
 

 
    // This should only run after engineId and engines array have been populated. 
 
    this.getEngineName(this.engineId); 
 
    } 
 

 
    getEngineName(engineId: number) { 
 
    this.engines.find((engine) => { 
 
     return engine.id === engineId; 
 
    }) 
 
    } 
 
}

+0

您可以使用combineLatest。您的问题与此类似:http://stackoverflow.com/questions/40872357/waiting-for-ngrx-action-before-loading-page-with-url-parameter/40905330#40905330 With combineLatest you do not need嵌套订阅。 – chrigu

回答

2

你为什么不只是移动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); 
    }); 
}); 

flatMapforkJoin

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); 
}); 
+1

啊!是。这非常有道理!非常感谢。这为我做了。 – Yathi

+0

@Yathi很高兴我可以帮助 – echonax

+1

只是想知道,因为我不知道它有什么更好的:在rxjs嵌套订阅确定吗?我个人试图避免它们,因为我认为代码更容易阅读,但也许我错了。 – chrigu

0

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在PARAMS变化,第一观察到this.route.params.pluck('engineId')将发出的数据,这将导致在未来观察的this.engineService.getEngines()被炒鱿鱼。现在假设在这个可观察数据发出之前路由发生了变化。在这里您需要取消getEngines可观察才能防止出错。这由switchMap完成。

switchMap如果外部可观察性被触发,则取消内部可观察性。

PS:我已避免保留任何状态,如this.engineId

+0

我完全不遵循这一点。你可以在代码中添加更多的注释以使其更清楚吗?另外,我会在哪里调用我的'itemService.getItems()'?我假设它在switchMap中的return语句之前。此外,为什么这比第一个答案更好? – Yathi

相关问题