【问题标题】:Angular 5 HttpInterceptor Error Handling with calling the error handling of the caller firstAngular 5 HttpInterceptor 错误处理,首先调用调用者的错误处理
【发布时间】:2018-09-19 07:46:06
【问题描述】:

我有一个全局 HttpInterceptor,它带有一个处理 HttpErrorResponse 的 catch 块。但我的要求是,当服务进行 http 调用并且还有错误处理程序时,我希望服务上的错误处理程序首先关闭。如果此服务上没有错误处理程序,那么我希望全局 HttpInterceptor 错误处理程序来处理它。

示例代码:

Http 拦截器:

@Injectable()
export class ErrorHttpInterceptor implements HttpInterceptor {

constructor(private notificationService: NotificationService) {}

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req)
  .catch(
    error => {
      if (error instanceof HttpErrorResponse) {
        this.notificationService.error('Error', 'Error in handling Http request');
      }

      return Observable.empty<HttpEvent<any>>();
    }
  );
 }
}

以及服务调用:

updateUser(id, data) {
  return this.http
    .patch(`${API.userUrl}/${id}`,  {data: data})
    .subscribe(
      () => console.log('success'),
      (err) => this.notificationService.error('custom code to handle this')
     );
}

在这种情况下,ErrorHttpInterceptor 会发出通知,然后 userService 错误处理也会发出错误通知。

但在我的用例中,我希望 ErrorHttpIntercetor 仅在底层订阅未处理错误时处理错误。有没有办法做到这一点?

【问题讨论】:

    标签: angular angular-http-interceptors angular-httpclient


    【解决方案1】:

    解决的一种方法是通过httpHeaders 请求:

     request() {  
        const url = 'GoalTree/GetById/'; 
        let headers = new HttpHeaders();
        headers = headers.append('handleError', 'onService');
        this.http.get(url, {headers: headers})
          .pipe(
          map((data: any) => {
            this.showError = false; 
          }),
          catchError(this.handleError)
          )
          .subscribe(data => {
            console.log('data', data);
          })
      }
    

    Interceptor.ts:

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    
        this.spinnerService.show();
    
        return next.handle(req).do(
          (event: HttpEvent<any>) => {
            if (event instanceof HttpResponse) {
              this.spinnerService.hide();
            }
          },
          (err: any) => {
            if (req.headers.get('handleError') === 'onService') {
              console.log('Interceptor does nothing...');
            } else {
              console.log('onInterceptor handle ', err);
            }
    
          }
        );
      }
    

    并检查interceptor 的错误回调中的请求标头。 但是在这个解决方案中,拦截器在任何服务调用之前处理请求。

    StackBlitz Example

    【讨论】:

    • 谢谢,这是一个聪明的方法。但这涉及重构大量代码以检查我们在服务层处理错误的位置并将标头附加到调用中。
    • @Nani,可以稍微简化一下。检查 header 的存在(无需检查 header 值),如:if(req.headers.has('inService')) {}
    • 哇,谢谢@Yerkon
    【解决方案2】:

    这是迄今为止我想出的最好的解决方案。

    在你的拦截器中,在错误对象上创建一个新的订阅属性,然后重新抛出你的错误:

    return next.handle(authReq).pipe(
        catchError((err: any, caught: Observable<HttpEvent<any>>) => {
            err.defaultHandler = timer(0).subscribe(() => {
                this.notify.error('Server Error', 'Server Error Message');
            });
            return throwError(err);
        })
    );
    

    在您想要实际处理错误的地方,取消订阅上面创建的计时器订阅:

    this.authService.login(authRequest).subscribe((x) => {
      this.navigateDefaultRoute();
    }, (err) => {
      // Prevent default error from being handled
      err.defaultHandler.unsubscribe();
    
      this.notify.error('Invalid Credentials', 'Email and password did not match');
    });
    

    【讨论】:

    • 不错的解决方案。谢谢
    猜你喜欢
    • 2020-04-26
    • 1970-01-01
    • 2016-03-30
    • 1970-01-01
    • 2010-12-16
    • 1970-01-01
    • 2018-05-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多