angular - Handle errors in a Resolve service -
say have valuescomponent
displays array of value
in html table.
// in value.ts export class value { ... }
// in values.component.ts @component(...) export class valuescomponent { ... }
being programmer , all, i've created different class responsible providing values. let's call valuesservice
.
// in values.service.ts @injectable() export class valuesservice { public getvalues(): observable<value[]> { ... } }
suppose service gets values web service: /api/values
now instead of injecting service directly component, want let angular router pre-fetch values before navigating component.
for that, created resolve
service class , plugged router module.
// in values-resolver.service.ts export class valuesresolverservice implements resolve<value[]> { constructor(private backend: valuesservice) { } public resolve(route: activatedroutesnapshot, state: routerstatesnapshot): observable<value[]> { return this.backend.getvalues(); } }
// in app.module.ts (in @ngmodule()) imports: [ routermodule.forroot([{ path: 'values', component: valuescomponent, resolve: { values: valuesresolverservice } }]) ]
// in values.component.ts public values: value[]; constructor(private route: activatedroute) { } ngoninit() { this.values = route.data.values value[]; }
how doing far? good? put error handling when valuesservice.getvalues()
fails? (connection error, internal server error, ...)
when user tries navigate /#/values
route , error occurs, want log error console , stop navigation. ideally, i'd redirect user /#/error
route (not shown in example code).
in such situation, service should handle error, , redirect wanted route. catch method should return empty observable (for resolve guard resolve), while handling empty cases during within resolve.
something this
export class valuesservice { constructor(private http:http, private router:router) {} getvalue() { this.http.get('/some/url').map((response:response) => { // map response model here }).catch((response:response) => { // handler case different status this.router.navigate(['/error']); return observable.empty(); }) } }
and guard following
export class valueresolveguard implements resolve<value[]> { constructor(private valueservice:valueservice) {} resolve() { // don't need route & state if you're not gonna use them this.valueservice.getvalue().topromise().then((values:values[]) => { if (!values) { // observable.empty() case // return default stuff } return values; }) } }
alternatively, if want return observable (shouldn't make difference in case, since resolve guard, accepts both observable , promise), can this.
this.valueservice.getvalue().first().catch({} => { // return default value. });
notice first() required, observable returned terminated observable, otherwise resolve guard wouldn't resolve. catch needed because first() call on empty observable throw error.
Comments
Post a Comment