I am on Angular 2.3.1 and I am fairly new to both Angular and event based programming. I have two subscriptions, route.params.subscribe
and engineService.getEngines()
. In my onInit
I want to call getEngineName
after this.route.params.subscribe
and this.engineService.getEngines().subscribe
plete.
Reason for this: getEngineName
functions depends on the engineId
from the queryParams and the engines
array which is populated after the pletion of getEngines()
call.
I did look at flatMap
and switchMap
but I did not pletely understand them.
This is the code in the ponent:
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;
})
}
}
I am on Angular 2.3.1 and I am fairly new to both Angular and event based programming. I have two subscriptions, route.params.subscribe
and engineService.getEngines()
. In my onInit
I want to call getEngineName
after this.route.params.subscribe
and this.engineService.getEngines().subscribe
plete.
Reason for this: getEngineName
functions depends on the engineId
from the queryParams and the engines
array which is populated after the pletion of getEngines()
call.
I did look at flatMap
and switchMap
but I did not pletely understand them.
This is the code in the ponent:
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;
})
}
}
Share
Improve this question
edited Jan 9, 2017 at 20:34
eko
40.7k11 gold badges78 silver badges101 bronze badges
asked Jan 9, 2017 at 20:17
YathiYathi
1,0611 gold badge14 silver badges21 bronze badges
1
- you could use bineLatest. Your problem is similar to this one: stackoverflow./questions/40872357/… With bineLatest you don't need to nest subscriptions. – chrigu Commented Jan 9, 2017 at 20:32
2 Answers
Reset to default 4Why don't you just move the logic inside the route.params
callback?
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);
});
});
with flatMap
and 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
is remended in this scenario.
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;
});
}
Suppose the engineId in the params changes, the first observable this.route.params.pluck('engineId')
will emit data, which will cause the next observable this.engineService.getEngines()
to get fired. Now suppose the route changes before this observable emits the data. Here you need to cancel getEngines
observable to prevent error. This is done by switchMap
.
switchMap
cancels inner observable if outer observable is fired.
PS: I have avoided keeping any states like this.engineId
etc.