在拦截器中捕获一些错误

时间:2018-08-08 07:58:07

标签: angular rxjs

我正在使用拦截器来处理未经授权的HTTP请求,该请求将显示模式或路由到登录页面。当拦截器处理错误时,我不希望发出原始请求的服务或组件也处理该错误。我确实希望组件或服务错误处理能够引发非401错误。

在我的拦截器中,我正在使用RxJS catchError捕获错误并检查错误详细信息。如果拦截器不会处理它,我只是将其与throwError一起抛出,这似乎可以正常工作。问题是我需要停止错误传播。如果不返回任何内容,则会出现以下错误:

  

错误TypeError:您在期望流的位置提供了“ undefined”。   您可以提供一个Observable,Promise,Array或Iterable。

使用of()返回一个空的Observable几乎可以,但是在加载应用程序时,控制台中出现以下错误。

  

错误错误:未捕获(按承诺):空错误:顺序中没有元素

我不知道原因或解决方法。我应该如何在拦截器中终止执行,从而基本上完成可观察的工作?这是我的代码:

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  constructor (
    private router: Router,
    private sessionService: SessionService
  ) {}

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    request = request.clone()
    return next.handle(request).pipe(
      catchError((err: any) => {
        if (err instanceof HttpErrorResponse) {
          if (err.status === 401 && this.router.url === '/') {
            this.router.navigateByUrl('/login')
          } else if (err.status === 401 && !/^\/activate-account/.test(this.router.url) && !/^\/log-?[i,I]n/.test(this.router.url)) {
            this.sessionService.setSessionExpired()  
          }
          return of()
        } else {
          return throwError(err)
        }
      })
    )
  }
}

3 个答案:

答案 0 :(得分:1)

为什么不能尝试Observable.empty()。它将停止传播并将处理程序返回到调用服务。

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  constructor (
    private router: Router,
    private sessionService: SessionService
  ) {}

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    request = request.clone()
    return next.handle(request).pipe(
      catchError((err: any) => {
        if (err instanceof HttpErrorResponse) {
          if (err.status === 401 && this.router.url === '/') {
            this.router.navigateByUrl('/login')
          } else if (err.status === 401 && !/^\/activate-account/.test(this.router.url) && !/^\/log-?[i,I]n/.test(this.router.url)) {
            this.sessionService.setSessionExpired()  
          }
          return Observable.empty();
        } else {
          return throwError(err)
        }
      })
    )
  }
}

答案 1 :(得分:0)

拦截器期望您使用catchError传输的return语句。如果不这样做,就不会尊重拦截器的签名,因此会出错。

为避免这种情况,请始终返回抛出的可观察值。您可以返回throwError(undefined),并且在错误处理中,如果看到错误是未定义的,则根本就不对待它。您甚至可以走得更远,并使用Rx通过.pipe(filter(err => !!err))过滤未定义的错误。

答案 2 :(得分:0)

问题似乎是由于在返回空的可观察对象之前导航离开了。我已将return语句移到特定的if条件中,以便在调用throwError(err)之后可以返回this.router.navigateByUrl,否则返回一个空的observable。我还使用了EMPTY的可观察常数(如Suresh Kumar Ariya所建议)

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  constructor (
    private router: Router,
    private sessionService: SessionService
  ) {}

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    request = request.clone()
    return next.handle(request).pipe(
      catchError((err: any) => {
        if (err instanceof HttpErrorResponse) {
          if (err.status === 401 && this.router.url === '/') {
            this.router.navigateByUrl('/login')
            return throwError(err)
          } else if (err.status === 401 && !/^\/activate-account/.test(this.router.url) && !/^\/log-?[i,I]n/.test(this.router.url)) {
            this.sessionService.setSessionExpired()
            return EMPTY
          } else {
            return throwError(err)
          }
        } else {
          return throwError(err)
        }
      })
    )
  }
}