As already mentioned in the comments, the catch shouldn't swallow the error in the first place, thats a nogo for sure. By doing that you are simply blocking the error signal in the rxjs chain.
Eventually you could do your logging in the catch and then re throw, but thats kinda overkill for only log side effect.
The simplest option would be to use the error callback arguent in the do
operator.
According to this tutorial page, the do operator can take 3 arguments (callback fns), what basically matches the subscribe signature:
1s argument: callback on next
2nd argument: callback on error
3rd argument: callback on complete
So you could refactor into the following:
callRemote() {
return this.http.get("http://aaa.dom")
.do(
response => console.log("logging response both bad and ok..."),
error => console.log("Something exploded, call 911");
}
So basically you could attach that operation to every single HttpClient
call in your base code. Pretty neat, no?
Wait wait! This might look neat on a first glance, but it will backfire at the very same moment that you want to:
- Modify the logging behavior
- Refactor in any way
Why?
You are going to basically monkey-patch every single possible back end call with that do() operation. And if making 1 change to that logic means changing code in more than 3 places, there something smelly going on.
A better approach
With the introduction of the HttpClient, another API was added: the HttpInterceptor API.
Basically, you could intercept all your outgoing requests in a single point.
How? As it follows:
First step, create an injectable service that you can use to capsulate the logging logic;
import { Injectable } from '@angular/core';
import {
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor
} from '@angular/common/http';
import { AuthService } from './auth/auth.service';
import { Observable } from 'rxjs/Observable';
import { tap } from 'rxjs/operators'; // fancy pipe-able operators
@Injectable()
export class LoggingInterceptor implements HttpInterceptor {
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(request).pipe(
tap(
response => console.log("Oh boy we got an answer"),
error => console.log("Something might be burning back there")
));
}
}
Second step, make angular aware of the existence of the LoggingInterceptor
by providing it through a token:
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { NgModule, ClassProvider } from '@angular/core';
import { LoggingInterceptor } from '../some-place';
const LOGGING_INTERCEPTOR_PROVIDER: ClassProvider = {
provide: HTTP_INTERCEPTORS ,
useClass: LoggingInterceptor,
multi: true
};
@NgModule({
...
providers: [
LOGGING_INTERCEPTOR_PROVIDER
]
...
})
export class AppModule {}
And thats it! Now you can log all your outgoing requests and do some other cool stuff with those logs if necessary, in a truly centralized way.
Observable.throw
it instead of turning it into a successful stream? Just log it where you catch it instead. – Ph.catch(f=>Rx.Observable.throw (f))
? If I do that - thendo
is not called. – Hypabyssal{ error, result }
and then unwrap it later, which seems kind of awkward. – Ph