我在Web上发现,ErrorHandler可以将所有错误捕获为客户端错误,也可以捕获HTTPErrorResponse错误. 但在我的情况下,我只能在GlobalErrorHandlerService中捕获客户端错误,而另一个httpErrorResponse则无法捕获. 我做错了什么?

My app-module:

  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: MainInterceptorService, multi: true },

    { provide: ErrorHandler, useClass: GlobalErrorHandlerService  },
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

My GlobalErrorHandler:

import {ErrorHandler, Injectable} from '@angular/core';
import {HttpErrorResponse} from "@angular/common/http";

@Injectable({
  providedIn: 'root'
})
export class GlobalErrorHandlerService implements ErrorHandler{

  constructor() { }

  handleError(error: any): void {
    console.log("Handler work")
    if (error instanceof HttpErrorResponse){

      console.log("HttpErrorResponse")
    } else {
      console.log("Not httpErrorResponse")
    }
 }
}

My intercepter:

import { Injectable } from '@angular/core';
import {HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from "@angular/common/http";
import {catchError, Observable, throwError} from "rxjs";
import {error} from "@angular/compiler-cli/src/transformers/util";


@Injectable({
  providedIn: 'root'
})
export class MainInterceptorService implements HttpInterceptor{
  private httpError = {
    status: 0,
    message: ''
  };


  constructor() { }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // req=req.clone({headers:req.headers.set("Auth","Bearer"+token)})

    return next.handle(req).pipe(
      catchError(
        (error:HttpErrorResponse|Error)=>{

      // server-side error
          if (error instanceof HttpErrorResponse){
            console.log("intercepter work")
            return throwError(()=>new Error("Server side error"+error));
          } else {
            return throwError(()=>new Error("Client side error"+error))
          }


        }
    )
    )
  }
}

My UserService

import { Injectable } from '@angular/core';
import {HttpClient, HttpErrorResponse} from "@angular/common/http";
import {User} from "../entity/user";


@Injectable({
  providedIn: 'root'
})
export class UserService {

  errors:any[]|undefined
  private response:Response|undefined

  constructor(private http:HttpClient) { }
  readonly URL_BASE="http://****"
  readonly URL_REGISTRATE="http://****"

  registrUser(user:User):any {

    return this.http.post<any>(this.URL_BASE+"/account/register", user)
  }

  loginUser(userName:string,password:string):any{

    return this.http.post<any>(this.URL_BASE+"/account/signin",{userName,password})
  }


}

如果你解释一下ErrorHandler的逻辑,那么我会很高兴的.

推荐答案

我想我现在了解了您的代码中发生了什么:

  • First你的MainInterceptorService会被叫来.如果出现服务器错误,则将HttpErrorResponse转换为Error对象.
  • Second,则命中GlobalErrorHandlerService,但由于您已经将错误转换为Error类型的对象,它将不再被识别为HttpErrorResponse,因此它被视为客户端错误.
  • 我还注意到:当我在registrUser()loginUser()中添加catchError()时,GlobalErrorHandlerService对于这些方法再是not次命中,因为本地catchError()接受了错误(但我仍然可以重新引发错误来触发GlobalErrorHandlerService;-))

因此,我们的目标必须是以不将原始错误类型转换为其他类型对象的方式重构MainInterceptorService.这可以通过以下方式完成:

export class MainInterceptorService implements HttpInterceptor {

  constructor() { }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // req=req.clone({headers:req.headers.set("Auth","Bearer"+token)})

    return next.handle(req).pipe(
      catchError(
        (err: HttpErrorResponse|Error)=>{
          if (err instanceof HttpErrorResponse){
            console.error('Server side error'+err);
          } else {
            console.error('Not a httpErrorResponse'+err);
          }
          return throwError(() => err);
        }
     )
    );
  }
}

Important:

  • 您实际上可以忘记我在前面的回答中提出的代码建议.除了我在上面展示的MainInterceptorService代码之外,一切都要保持原样.
  • 请注意,客户端错误可能不会进入HttpInterceptor,因为它们通常与http请求无关.
  • 您基本上使用ErrorHandler来处理客户端错误,使用HttpInterceptors来处理与http请求相关的错误.
  • 在以下链接下,您可以找到一个与错误相关的HttpInterceptor可能是什么样子的示例:Global ErrorHandler is not working after implementing catchError in ngrx effect

Angular相关问答推荐

HTTP POST响应失败Angular 16

PathMatch full始终连接到参数化路径,即使完整路径不匹配也是如此

如何使用formBuilder.Group()从角形表单中删除选定的选项?

Angular 17+独立配置中main.ts bootstrap 调用的最佳实践

ANGLE v16独立组件不能与拦截器一起工作?

等待可观察性完成后再调用下一个

用于 React 的 ngx-extended-pdf-viewer

使用 TAB 键时如何聚焦mat-select组件?

使用 RXJS 进行空闲/不活动跟踪

Angular SPA 和 .Net 6 API 之间未连接 Application Insights Map

带有 Angular 2 的 Django

Angular 6 - NullInjectorError:单元测试中没有 HttpClient 的提供者

如何以Angular 获取嵌套表单组的控件

为什么我们需要`ngDoCheck`

Angular 2 单元测试 - @ViewChild 未定义

默认情况下如何在Angular中 Select mat-button-toggle

Angular 4 Bootstrap 下拉菜单需要 Popper.js

Angular 2 更改事件 - 模型更改

angular2 测试,我如何模拟子组件

包 '@angular/cli' 不是依赖项