0

On a service in Angular, in the following api call, what is the way to catch an error:

getData(sourceId: string): Observable <Array<CustomObject>> {
    const obs: BehaviorSubject<Array<CustomObject>> = this.servicesObsCache[sourceId];
    const options = new RequestOptions({...});
    this.http
        .get(API_URL + 'sourceId' + '/serviceendpoint', options, true)
        .map(res => res.json())
        .first()
        .subscribe(
            body => {
                ...
                obs.next(services);
            },
            err => {
                obs.next(err); // Is this statement allowed on error?
                obs.error(err);
            }
        );
    return obs.filter((results) => !!results);
}

I have tried to use obs.next(err); but I believe it doesn't catches the error when api fails and instead takes it as success.

What should I use so as to allow the method which invokes the getData(<custom_id>), catch the error?

Shashank
  • 2,010
  • 2
  • 18
  • 38
  • you can throw the `error` as `return Observable.throw(err);` and then catch it where you are calling `getData()` – Anshuman Jaiswal Apr 12 '18 at 11:50
  • What do you mean by "catch"? For example be able to print the error or want to turn it into `next` or what? – martin Apr 12 '18 at 12:54
  • @martin Similar to `next` as I am able to get the error object, but the console logs as *Uncaught*. The `next()` treats it as success itself. So I guess, it is not advisable. – Shashank Apr 12 '18 at 13:27
  • @AnshumanJaiswal Ideally `Observable.throw(err);` should work but unfortunately it didn't. – Shashank Apr 12 '18 at 13:30

2 Answers2

0
You have to catch http error before subscription like the following.
this.http.get(url).map((response) => response).catch((e) => {
   //Catching based on http error code.
   if(e.status == 400){
   //Do anything based on http status code.
}

//Throw Custom error message.
return Observable.throw(new Error(`${ e.status } ${ e.statusText }`));
});
0

I researched the difference between BehaviorSubject and Observable and found that the former is stateful while the latter one is stateless.

I inspected my code and found that, since I was using BehaviorSubject, on error, being it stateful, it always contained the error obect. Due to which, when I tried to execute the following code before making the api call:

obs.getValue();

it returned the error by breaks the ideal flow and prevented from making the service call.

As a result, I used Observable as below:

getData(sourceId: string): Observable<Array<CustomObject>> {
    return Observable.create(obs => {
        const options = new RequestOptions({ ...});
        this.http
            .get(API_URL + 'sourceId' + '/serviceendpoint', options, true)
            .map(res => res.json())
            .first()
            .subscribe(
                body => {
                ...
                obs.next(services);
            },
            err => obs.error(err);
        );
    });
}

Using this, the error gets handled by Observable error handling through its subscription.

Also, the following code should not be used in error handling:

obs.next(err);

although, it sends the required error object to the calling service, but it does so on success and not on error. In short, it is not a good practice to catch the error.

Shashank
  • 2,010
  • 2
  • 18
  • 38