web-dev-qa-db-ja.com

Angular 5呼び出し元のエラー処理を最初に呼び出すHttpInterceptorエラー処理

HttpErrorResponseを処理するcatchブロックを持つグローバルHttpInterceptorがあります。しかし、私の要件は、サービスが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でエラーを処理します。これを行う方法はありますか?

8
Nani

解決する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);
        }

      }
    );
  }

リクエストヘッダーのin interceptorのエラーコールバックを確認してください。ただし、このソリューションでは、Interceptorsがサービスを呼び出す前にリクエストを処理します。

StackBlitzの例

2
Yerkon

これは私がこれまでに思いついた最良の解決策です。

インターセプターで、エラーオブジェクトに新しいサブスクリプションプロパティを作成し、エラーを再スローします。

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');
});
0
Chris Fremgen