我在网上发现ErrorHandler可以捕获所有错误作为客户端错误和httpErrorResponse
错误。
但是在我的情况下,我只能在GlobalErrorHandlerService中捕获客户端错误,另一个httpErrorResponse
不能被捕获。我做错了什么?
我app-module:
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: MainInterceptorService, multi: true },
{ provide: ErrorHandler, useClass: GlobalErrorHandlerService },
],
bootstrap: [AppComponent]
})
export class AppModule { }
我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")
}
}
}
我的拦截器:
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))
}
}
)
)
}
}
我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的逻辑,那就太好了。
我想我现在明白你的代码是怎么回事了:
首先- 你的
MainInterceptorService
被调用。如果您得到一个服务器错误,您可以将HttpErrorResponse
转换为Error
-对象。 第二>,您的
GlobalErrorHandlerService
被击中,但由于您已经将错误转换为类型为Error
的对象,它将不再被识别为HttpErrorResponse
,因此它被视为客户端错误。我还注意到:当我在registrUser()
或loginUser()
中添加catchError()
时,GlobalErrorHandlerService
是而不是因为本地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);
}
)
);
}
}
重要:
- 您实际上可以忘记我在之前的回答中提出的代码建议。除了上面显示的
MainInterceptorService
代码外,所有内容保持原样即可。 请注意,客户端错误可能不会进入 - 你基本上使用
ErrorHandler
来处理客户端错误,HttpInterceptors
来处理与http请求相关的错误。 - 在下面的链接下,你可以找到一个关于错误相关的
HttpInterceptor
的例子:在ngrx效果中实现catchError后,全局ErrorHandler不工作
HttpInterceptor
,因为它们通常与http请求无关。