Issue
Suppose I have some operation that returns an observable.
this.loginService
.post<IResponse>(url, { username, password })
.subscribe(
next => { /* I know the type of next */ },
error => { /* Can I specify type of err, or is it always any? */ }
);
The type of next
is something I can set - in this case IResponse
.
What about error
- can I specify it's type somehow? Or is it always any
, and I'll always need to typecast within the handler?
Solution
It's been my experience that a service that yields observables from a HTTP operation should never emit uncaught HTTP errors. It creates a lot of boilerplate code in the consumers of that service, and forces consumers to handle HTTP specific issues.
I also think that services should not catch all types of errors, but only the known and expected errors. Requiring the application itself to handle edge cases using an error interceptor.
export interface ILoginResponse {
//...
}
export interface IServiceResponse<TType> {
success: boolean;
payload?: TType;
}
@Injectable()
export class LoginService {
public login(options: any): Observable<IServiceResponse<ILoginResponse>> {
return this.httpClient.post<ILoginResponse>('login', options).pipe(
map(payload => ({success: true, payload})),
catchError(err => {
if(err instanceof HttpErrorResponse) {
// handle http errors here, maybe retry, update headers, etc..
return of({success: false});
}
// this error is unexpected, we don't know what to do
// let the app interceptor handle it, but upstream observables
// won't know what to do either. Our app has crashed...
// You can return success false, but why handle this error?
return throwError(err);
});
}
}
Why should you do the above?
Any time you use a route resolver that emits an uncaught error it will fail route transition. The router will basically crash. The user will basically just see a blank page, because resolvers have no error handling fall back.
The above only catches HTTP errors, because that's the only kind that we think should be thrown. Another kind of error should be seen as a bug.
If a component calls this service, then the programmer should check the success
flag for true
before trusting the emitted value. This can be filtered if the business logic does not care if it fails, or the component can visually show the user that it failed to perform the HTTP request. Either way, the HTTP error response does not go to the app error interceptor.
This is just an approach. People do their HTTP stuff all differently. The other answer correctly answers your question.
Answered By - Reactgular
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.