Search code examples
node.jsangularerror-handlingobservable

How to handle error while returning an observable in angular?


I am creating an AuthGuard for my app..now when i try to load the component without getting logged in it should redirect me to the login page..But i am getting an error like following image error

and nothing happens.

I am throwing this error from my backend {"status":401,"message":"Auth Token Not found!"}} as there is no auth token

The following is the code of my AuthGuard

export class AuthGuardService implements CanActivate {

  constructor(private authService: AuthService, private router: Router) { }

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | Observable<boolean> {

    return this.authService.checkLogin().pipe(
      map((data: HttpResponse) => {
        if (data.status == 200) {
          console.log("OUTPUT:", data)
          return true
        }
        else return false
      }),
    )

  }
}

The following is my function in AuthService:

 public checkLogin():Observable<HttpResponse> {

    return this.http.get<HttpResponse>('http://localhost:5000/auth/check-login', { withCredentials: true })

  }

Now how can i handle the errors like these and set a fallback value to false so if any error occurs then that route could not be accessed


Solution

  • If I understood you correctly you want to achieve the following behavior:

    • If checkLogin() gets a response that indicates "success", the auth-guard shall return true
    • If checkLogin() gets an error-response, redirect the user to a fallback-page and return false

    If you use the code below, please note that catchError() is only triggered if the backend responds with an exception, while map() is always triggered if a success-response comes in from the backend. Therefore, in the positive case, you can simply return true without checking the contents of the response. However, if you receive an exception from the backend, you can redirect the user to the fallback page using this.router.navigate() and then return of(false) to prevent the request from passing the auth guard.

    export class AuthGuardService implements CanActivate {
    
      constructor(private authService: AuthService, private router: Router) { }
    
      canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | Observable<boolean> {
    
        return this.authService.checkLogin().pipe(
          map(() => true),
          catchError(() => {
            this.router.navigate(['route-to-fallback-page']);
            return of(false);
          })
        );
      }
    }
    

    Alternative solution for Angular 7.1+

    Starting from Angular 7.1 you can just return a UrlTree-Object containing the fallback-route:

      canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> {
    
        return this.authService.checkLogin().pipe(
          map(() => true),
          catchError(() => this.router.parseUrl('/route-to-fallback-page'))
        );
      }