2017-01-09 81 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

相關問題