Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it impossible to catch errors inside a subscription?

I am using Angular 7 where I am trying to catch an error thrown because a value returned by the external api had null values where I expected values.

I can't seem to figure out what I am supposed to do in this scenario.

I have a service that call the api.

getObjectValue(param: paramtype): Observable<ObjectValue> {
    return this.http.get<objectwithvalues>(environment.baseapiurl + '/api/object/value/'+ param);
  }

In the consuming component I subscribe like I always would

testfunction() {
   this.service.getObjectValue().Subscribe(v => {
    *DO STUFF*
    *Error happens* v['o'] // oh no v is null
   },
    error=>{
     console.log('error') 
     this.snackbar.open('this went wrong' + error); 
    }
  );
}

That is the basic case. Doing this does not trigger 'error=>{}' Angular simply spits out an error message.

So I tried try/catch within the subscribe callback scope. Did not catch.

I am currently trying to change the service code to the following

getObjectValue(param: paramclass): Observable<ObjectValue> {
    return this.http.get<EventWifi>(
      environment.baseapiurl + '/api/object/value/'+ param).pipe(map(v=> {
   if(v === null){
     return throwError('v is null');  
   } 
  }),
   catchError(err => this.errorTest(err))
);
  }

this.errorTest(err: any): Observable<any> {
 return throwError(err);

}

While doing the same in the subscriber, but the error is never caught by the subscribing error function so I am unable to handle the error appropriately.

With the latest shown service function no error is thrown at all.

I have tried so many small differences in configuration I can hardly remember at this point, so there must be a basic thing I am messing up.

I have looked at so many examples but none of them catch and work in my case.

like image 438
Mikkel Avatar asked Mar 28 '19 14:03

Mikkel


People also ask

How do you return an observable error?

Angular ThrowError operator returns an observable, which on subscription immediately errors out. It does not emit any results.

How do you catch observable errors?

Catch errors in the observable stream Another option to catch errors is to use the CatchError Operator. The CatchError Operators catches the error in the observable stream as and when the error happens. This allows us to retry the failed observable or use a replacement observable.

What is catchError?

RxJS catchError() operator is an error-handling operator used to handle and take care of catching errors on the source observable by returning a new observable or an error.

How do you handle errors in RxJS subscription?

RxJS has operators designed to help you handle errors. Read on to learn these useful ones: catch and catchError , retry , and retryWhen . catch and catchError are used in more general situations. retry and retryWhen can be geared more towards specific errors that need special handling.


Video Answer


2 Answers

The issue is that you are trying to handle the error inside your subscription function. This will never reach your error function, simple because it can't. You should throw the error from within a pipe. Preferably in the mergeMap:

getObjectValue(param: paramtype): Observable<ObjectValue> {
  return this.http.get(environment.baseapiurl + '/api/object/value/'+ param).pipe(
    mergeMap((v) => v == null ? throwError('v is null') : of(v)) 
  );
}

You can then do this:

testfunction() {
  this.service.getObjectValue().subscribe((v) => {
    // v will never be null
  },
  (error) => {
    console.log('error') 
    this.snackbar.open('this went wrong' + error); 
  });
}

If this is something that occurs a lot in your application, you can create a HttpInterceptor which does this for you. You can make it throw the http call with a certain error code and number if the return value is null.

like image 198
Poul Kruijt Avatar answered Oct 29 '22 02:10

Poul Kruijt


Your error is that you are returning an Observable of an Observable while doing a throwError in map, use mergeMap instead.

return this.http.get<EventWifi>(url).pipe(mergeMap(v=> {
   if(v === null){
     return throwError('v is null');  
   } else {
        return of(v)
   } 
})

Under subscribe, an Observable is not an error.

https://stackblitz.com/edit/angular-uglwbm

like image 23
Ashish Ranjan Avatar answered Oct 29 '22 01:10

Ashish Ranjan