Angular 6 Observable chaining and error handling
Clash Royale CLAN TAG#URR8PPP
Angular 6 Observable chaining and error handling
I am getting the param via observable and if it is of proper enum type then i fetch data. I am not using snapshot for getting the param. This needs to use observable.
Also, there is a refresh button on the page and it just calls the second data method directly since we'll have the correct enum available to fetch data for.
Currently the following works for me.
export class MaintainComponent implements OnInit, OnDestroy
grouptType: zGroupTypes;
title: string = "";
isError: boolean = false;
errorMessage: string = "";
groupList: Group;
//handles to destroy the observables manually
activatedRouteSubscription: Subscription;
groupSubscription: Subscription;
constructor(private activatedRoute: ActivatedRoute, private router: Router, private dataService: DataService)
ngOnInit()
this.title = "";
this.isError = false;
this.errorMessage = "";
this.groupList = ;
this.checkAndGetData();
ngOnDestroy()
this.activatedRouteSubscription.unsubscribe();
this.groupSubscription.unsubscribe();
onRefresh()
this.getGroupInfo();
checkAndGetData()
this.activatedRouteSubscription = this.activatedRoute.params.subscribe(
(params: Params) =>
this.grouptType = <zGroupTypes>params['type'];
if (this.grouptType && this.grouptType in zGroupTypes)
//good
this.title = zGroupTypes[this.grouptType];
//get the group info
this.getGroupInfo();
else
//error - redirect to resource missing
this.router.navigate(['resource-missing']);
);
getGroupInfo()
this.groupList = ;
this.isError = false;
this.errorMessage = "";
const params = new HttpParams().set('groupType', this.grouptType.toString());
this.groupSubscription = this.dataService.pull<Group>(`$this.dataService.endPointGroup/GetGroupByAttributeId`, params).subscribe(
res =>
//res is of type Group
if (!res ,
error =>
this.isError = true;
this.errorMessage = "Error happened"; //console.log(error);
);
I want to rewrite this so that i don't use an observable inside an observable. After some reading, i have to use mergeMap but then how to
I found an example online to do chaining which looks like
export class AppComponent
homeworld: Observable<>;
constructor(private http: HttpClient)
ngOnInit()
this.homeworld = this.http.get('/api/people/1').pipe(
mergeMap(character => this.http.get(character.homeworld))
);
but then this doesn't show how to handle errors.
I started some thing like following but i am kind of lost since i am still relatively new to angular and operators are still not my strong point.
getData()
let singleCall = this.activatedRoute.params.pipe(
map(params =>
this.grouptType = <zGroupTypes>params['type'];
),
filter(() => this.grouptType && this.grouptType in zGroupTypes),
mergeMap(() =>
const paramToPass = new HttpParams().set('groupType', this.grouptType.toString());
this.dataService.pull<Group>(`$this.dataService.endPointGroup/GetGroupByAttributeId`, paramToPass)
.... how to proceed here
)
);
or is it safe to say that my original approach is still proper way of handling this situation.
1 Answer
1
In map
function, you must return new value. Don't assign side-effect inside it. Moreover, in this case, you should use switchMap
instead of mergeMap
map
switchMap
mergeMap
getData()
let singleCall = this.activatedRoute.params.pipe(
map(params => params.type),
tap((groupType) => this.groupType = groupType),
filter((groupType) => groupType && groupType in zGroupTypes),
switchMap(() =>
const paramToPass = new HttpParams().set('groupType', this.grouptType.toString());
return this.dataService.pull<Group>(`$this.dataService.endPointGroup/GetGroupByAttributeId`, paramToPass)
)
);
EDIT: If you want to switch case of groupType
, you can extend to 2 Observable
groupType
Observable
const param$ = this.activatedRoute.params.pipe(
map(params => params.type),
tap((groupType) => this.groupType = groupType),
);
param$.pipe(
filter((groupType) => !(groupType && groupType in zGroupTypes)),
).subscribe(() =>
console.error("Failed")
);
param$.pipe(
filter((groupType) => groupType && groupType in zGroupTypes),
switchMap(() =>
const paramToPass = new HttpParams().set('groupType', this.grouptType.toString());
return this.dataService.pull<Group>(`$this.dataService.endPointGroup/GetGroupByAttributeId`, paramToPass)
)
).subscribe((results) =>
// to do
);
this.getData.observable( res => ..., error => ...);
Yes, it is. However, if you want
getData
return Observable, run must replace let singleCall =
to return
. Moreover, the correct syntax is this.getData.subscribe
, not this.getData.observable
. You can subscribe after pipe too, no need to return getData as Observable– hgiasac
Aug 12 at 6:15
getData
let singleCall =
return
this.getData.subscribe
this.getData.observable
this.grouptType
is undefined inside switchMap. filter has groupType but it is not being assigned to this.groupType– learning...
Aug 12 at 6:18
this.grouptType
If you want to set
this.groupType
, you can append tap((groupType) => this.groupType = groupType)
after map
(see my example)– hgiasac
Aug 12 at 6:23
this.groupType
tap((groupType) => this.groupType = groupType)
map
I think the step of getting param don't affect much about performance. However, if you want to use cached
this. groupType
on refreshing, you can use expression like this: const param$ = this. groupType ? of(this.groupType) : this.activatedRoute...
. of
function will wrap the value into observable. The remain code is the same– hgiasac
Aug 12 at 7:45
this. groupType
const param$ = this. groupType ? of(this.groupType) : this.activatedRoute...
of
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
what is getData() returning, is it observable? So, if groupType isn't good then switchMap will not execute, am i correct? and i am going to handle error in the refresh and ngonInit, some thing like
this.getData.observable( res => ..., error => ...);
– learning...
Aug 12 at 5:54