Search code examples
angularinterceptor

Angular 9 - interceptor - what to return if no error in catcherror?


I have an interceptor in an angular app

the whole idea is that there is a jwt token valid for 30'

  • once in a while I get an error from the status code, so I deal with it

  • but sometimes, there is no error, so I dont want to throw any exception

since I don't return anything I get this error

You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.

unless I throw fake exceptions like throwError("OK");

here is my intercept function

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> 
{
    
    return next.handle(request).pipe(catchError(err => 
    {
        const error = (err.error?err.error.message:null) || err.statusText;

        switch (err.status) {
            case 401:
            {
                // token expired -> goto login, dont return error
                this.appService.clearUserSession();
                this.router.navigate(['login']);
                <<<<<<<<<<<<<<< HERE I DON'T WANT TO THROW AN ERROR, WHAT TO RETURN ?
            }
            break;
            case 500:
            {
                return throwError(error);
            }
            break;
            default:
            {
                  if(error!="OK")
                  {
                       return throwError(error);
                  }
                  else
                  {
                       // some errors are "OK", just ignore them
                       <<<<<<<<<<<<<<< HERE I DON'T WANT TO THROW AN ERROR, WHAT TO RETURN ?
                  }
            }
            break;
       }
      
    }))

  }

what do I return in place of <<<<<<<<<<<<<<<<<<<<<<<<<<<< ????

thanks for helping me


Solution

  • Like the error says, the RxJS catchError operator must return an observable. But when you wish to not throw the error you can use RxJS of function to return a valid notification. It will invoke the next callback of the observable instead of the error.

    import { of } from 'rxjs';
    
    intercept(request: HttpRequest < any > , next: HttpHandler): Observable < HttpEvent < any >> {
      return next.handle(request).pipe(catchError(err => {
        const error = (err.error ? err.error.message : null) || err.statusText;
        switch (err.status) {
          case 401: {
            // token expired -> goto login, dont return error
            this.appService.clearUserSession();
            this.router.navigate(['login']);
            return of(error);      // <-- return observable using `of`
          }
    
          case 500: {
            return throwError(error);
          }
    
          default: {
            if (error != "OK") {
              return throwError(error);
            }
            return of(error);      // <-- return observable using `of`
          }
        }
      }));
    }
    

    Or if you do not wish to call the next callback, you could return EMPTY constant to complete the observable.

    import { EMPTY } from 'rxjs';
    
    default: {
      if (error != "OK") {
        return throwError(error);
      }
      return EMPTY;      // <-- complete the observable
    }