I am relatively new to rxjs and angular. I have a projectRev that I need to retrieve, then I want to retrieve its parent. The API dictates two calls...
I have read a lot of SO about queuing Observables but they are all trivial and I am getting lost converting the trivial example into something that applies to me.
Here is something that does work... Once the first observable is done, call the second one. Simple?
My question: is there a TECHNICAL reason this approach is flawed. Again... it works. At least on a dev machine that isn't stressed out....
Thanks
getItems() {
console.log('get project rev');
let prId = this.activatedRoute.snapshot.params.id;
console.log(prId);
this.projrevSvc.getItemById(prId).subscribe(
(data) => {
console.log('this was fetched : ' data);
this.myItem = data;
this.getProj();
});
} //getItems
getProj() {
console.log('pr.pid ' this.myItem.ProjectId);
this.projectSvc.getItemById(this.myItem.ProjectId).subscribe(
(data) => {
console.log('this project was fetched : ' data);
this.myProject = data[0];
console.log('prid ' this.myItem.id)
console.log(this.myProject);
});
}
CodePudding user response:
Your code works. No one can deny that it will work. If the route were to fire often, you would have issues, in that if the route changed and the first call to getProj
returned AFTER the second call to getProj
, then you would have stale data. So, while it works, it's not fail proof.
The following uses a switchMap
so that follow up calls get cancelled and we never risk having stale data.
this.projrevSvc.getItemById(prId)
.pipe(
switchMap(item => {
return this.projectSvc.getItemById(item.ProjectId)
.pipe(
map(project => ([item, project])
);
})
).subscribe(([item, project]) => console.log(item, project))
AND THEN... you should make the stream fully reactive by consuming the params.id
as an observable... see here:
this.activatedRoute.params
.pipe(
pluck('id'),
switchMap(id => this.projrevSvc.getItemById(id))
switchMap(item => {
return this.projectSvc.getItemById(item.ProjectId)
.pipe(
map(project => ([item, project])
);
})
).subscribe(([item, project]) => console.log(item, project))
Then feel good because you wrote some fully reactive code that reacts to the changes from the state in the router. Pretty rad.
CodePudding user response:
You need to check this article for more information https://blog.angular-university.io/rxjs-higher-order-mapping/
But in short answer, you can use something like that
getElements() {
let prId = this.activatedRoute.snapshot.params.id;
this.projrevSvc.getItemById(prId)
.pipe(switchMap(response => this.projectSvc.getItemById(response.ProjectId)))
.subscribe((nestedReponse) => this.myItem = nestedResponse);
}