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.