Angular: 错误处理 - 拦截器和模态
Angular: Error handling - Interceptors and modals
我构建了一个 Angular 5 应用程序,它处理我发出的每个调用的错误。使用 HttpClient 我能够拦截在向服务器发送请求后发生的错误。该错误在将请求发送到 API 的服务方法上被拦截,然后当发生错误时,它被推送到组件以显示带有错误消息的漂亮模式。
我想使用拦截器来实现相同的行为,以便以一种集中的方式处理所有错误。但我不确定是否可以从拦截器 class 与组件通信,将消息发送给它,以便它可以像当前一样触发模态,
或如何直接从拦截器 class.
触发模态
这是我目前的逻辑:
组件:
....
export class VerificationComponent implements OnInit {
//Use to call the modal when errors happen
@ViewChild('modalError') displayErrorRef: ModalComponent;
//Method send a request to the api using a service instance _myService
getNextRecord() {
this.errorMesage = "";
this._myService.getCandidate()
.subscribe(candidate => {
this.loadCandidate = candidate;
this.userName = this.appService.getUser();
}, error => {
this.errorMesage = <any>error.errorMessage;
this.displayErrorRef.show();
});
}
}
....
服务:
.....
@Injectable()
export class MyService {
getCandidate(): Observable<ICandidate> {
return this._http.get(this._getCandidateUrl, this.jwt())
.map((response: Response) => <ICandidate>response.json())
.catch(this.handleError);
}
private handleError(error: Response) {
if (error.text())
return Observable.throw({errorMessage:error.text(),erroStatus: error.status });
else
return Observable.throw('You are not authorised to get this resource');
}
}
....
模板:
<!-- This is a child component to display the error message on the top of
this template -->
.....
<app-modal #modalError>
<div class="app-modal-header">
Error
</div>
<div class="app-modal-body">
{{errorMesage}}
</div>
<div class="app-modal-footer">
<button type="button" class="btn btn-default" (click)="hideModalError()">Logout</button>
<button type="button" class="btn btn-default"(click)="tryGetNextRecord()">Try Again</button>
</div>
</app-modal>
....
我建议创建 ResponseInterceptor 和 ErrorHandlerService 以拦截不良响应(500 等)并触发处理错误的集中式服务。
到目前为止,我认为服务与组件通信的最佳方式是使用 Observables。与此类似的内容:
// ErrorHandlerService
private errorEvent = new Subject();
public errorEvent$ = this.errorTrigger.asObservable();
public triggerError(error: any): void {
// manipulate your error here and then:
this.errroEvent.next(error);
}
//ResponseInterceptor
constructor(private errorHandlerService) {}
enter code here
intercept(...): ... {
//must check if response is an error to then:
this.errorHandlerService.triggerError(response);
}
// Your component
fetchData() {
this.errorHandlerService.errorEvent$.subscribe((error) => {
// here you have the error to manipulate in your component
});
this.anyOtherService.fetchObject().subscribe();
}
希望这对您正在寻找的内容有所帮助
对于使用 HttpInterceptor 的全局错误处理程序示例,您需要以下内容。
- 错误拦截器
- 错误服务
- CustomErrorModal
流量为:
app.module
=> 注册拦截器。
app.module
=> 将错误服务注册为提供商。
app.component
=> 注册显示错误模式的全局错误处理。
YourCustomComponent
=> 不订阅错误的Subject/Observable
您的主要 app.component 将 subscribe 来自错误服务的任何更新,并使用模态参考相应地显示它们。
app.module
//other code
const interceptors = [{
provide: HTTP_INTERCEPTORS,
useClass: ErrorInterceptor,
multi: true
}];
const services = [{
ErrorService
}];
@NgModule({
//other code
providers: [
interceptors,
services
],
//other code
})
error.service
@Injectable()
export class ErrorService
{
private errors = new Subject<string[]>();
constructor() { }
public addErrors = (errors: string[]): void =>
this.errors.next(errors);
public getErrors = () =>
this.errors.asObservable();
}
error.interceptor
@Injectable()
export class ErrorInterceptor implements HttpInterceptor
{
constructor(private errorService: ErrorService)
{
}
intercept(
request: HttpRequest<any>,
next: HttpHandler): Observable<HttpEvent<any>>
{
return next.handle(request).do(() => { }, (response) =>
{
if (response instanceof HttpErrorResponse)
{
if (response.status === 401)
{
return;
}
if (response.status === 400 &&
response.error)
{
this.errorService.addErrors(Array.isArray(response.error) ? response.error : [response.error]);
return;
}
this.errorService.addErrors([`Your generic error message`]);
}
return Observable.throw(response);
});
}
}
app.component
export class AppComponent implements OnDestroy
{
private ngUnsubscribe = new Subject();
@ViewChild('modalError')
displayErrorRef: ModalComponent;
constructor(private errorService: ErrorService)
{
this.initializeErrors();
}
ngOnDestroy()
{
this.ngUnsubscribe.next();
this.ngUnsubscribe.complete();
}
private initializeErrors()
{
this
.errorService
.getErrors()
.pipe(takeUntil(this.ngUnsubscribe))
.subscribe((errors) =>
{
//this.displayErrorRef.error = errors
this.displayErrorRef.show();
});
}
}
ngUnsubscribe
是当你的主 app.component
被销毁时自动处理订阅。
我构建了一个 Angular 5 应用程序,它处理我发出的每个调用的错误。使用 HttpClient 我能够拦截在向服务器发送请求后发生的错误。该错误在将请求发送到 API 的服务方法上被拦截,然后当发生错误时,它被推送到组件以显示带有错误消息的漂亮模式。
我想使用拦截器来实现相同的行为,以便以一种集中的方式处理所有错误。但我不确定是否可以从拦截器 class 与组件通信,将消息发送给它,以便它可以像当前一样触发模态, 或如何直接从拦截器 class.
触发模态这是我目前的逻辑:
组件:
....
export class VerificationComponent implements OnInit {
//Use to call the modal when errors happen
@ViewChild('modalError') displayErrorRef: ModalComponent;
//Method send a request to the api using a service instance _myService
getNextRecord() {
this.errorMesage = "";
this._myService.getCandidate()
.subscribe(candidate => {
this.loadCandidate = candidate;
this.userName = this.appService.getUser();
}, error => {
this.errorMesage = <any>error.errorMessage;
this.displayErrorRef.show();
});
}
}
....
服务:
.....
@Injectable()
export class MyService {
getCandidate(): Observable<ICandidate> {
return this._http.get(this._getCandidateUrl, this.jwt())
.map((response: Response) => <ICandidate>response.json())
.catch(this.handleError);
}
private handleError(error: Response) {
if (error.text())
return Observable.throw({errorMessage:error.text(),erroStatus: error.status });
else
return Observable.throw('You are not authorised to get this resource');
}
}
....
模板:
<!-- This is a child component to display the error message on the top of
this template -->
.....
<app-modal #modalError>
<div class="app-modal-header">
Error
</div>
<div class="app-modal-body">
{{errorMesage}}
</div>
<div class="app-modal-footer">
<button type="button" class="btn btn-default" (click)="hideModalError()">Logout</button>
<button type="button" class="btn btn-default"(click)="tryGetNextRecord()">Try Again</button>
</div>
</app-modal>
....
我建议创建 ResponseInterceptor 和 ErrorHandlerService 以拦截不良响应(500 等)并触发处理错误的集中式服务。
到目前为止,我认为服务与组件通信的最佳方式是使用 Observables。与此类似的内容:
// ErrorHandlerService
private errorEvent = new Subject();
public errorEvent$ = this.errorTrigger.asObservable();
public triggerError(error: any): void {
// manipulate your error here and then:
this.errroEvent.next(error);
}
//ResponseInterceptor
constructor(private errorHandlerService) {}
enter code here
intercept(...): ... {
//must check if response is an error to then:
this.errorHandlerService.triggerError(response);
}
// Your component
fetchData() {
this.errorHandlerService.errorEvent$.subscribe((error) => {
// here you have the error to manipulate in your component
});
this.anyOtherService.fetchObject().subscribe();
}
希望这对您正在寻找的内容有所帮助
对于使用 HttpInterceptor 的全局错误处理程序示例,您需要以下内容。
- 错误拦截器
- 错误服务
- CustomErrorModal
流量为:
app.module
=> 注册拦截器。
app.module
=> 将错误服务注册为提供商。
app.component
=> 注册显示错误模式的全局错误处理。
YourCustomComponent
=> 不订阅错误的Subject/Observable
您的主要 app.component 将 subscribe 来自错误服务的任何更新,并使用模态参考相应地显示它们。
app.module
//other code
const interceptors = [{
provide: HTTP_INTERCEPTORS,
useClass: ErrorInterceptor,
multi: true
}];
const services = [{
ErrorService
}];
@NgModule({
//other code
providers: [
interceptors,
services
],
//other code
})
error.service
@Injectable()
export class ErrorService
{
private errors = new Subject<string[]>();
constructor() { }
public addErrors = (errors: string[]): void =>
this.errors.next(errors);
public getErrors = () =>
this.errors.asObservable();
}
error.interceptor
@Injectable()
export class ErrorInterceptor implements HttpInterceptor
{
constructor(private errorService: ErrorService)
{
}
intercept(
request: HttpRequest<any>,
next: HttpHandler): Observable<HttpEvent<any>>
{
return next.handle(request).do(() => { }, (response) =>
{
if (response instanceof HttpErrorResponse)
{
if (response.status === 401)
{
return;
}
if (response.status === 400 &&
response.error)
{
this.errorService.addErrors(Array.isArray(response.error) ? response.error : [response.error]);
return;
}
this.errorService.addErrors([`Your generic error message`]);
}
return Observable.throw(response);
});
}
}
app.component
export class AppComponent implements OnDestroy
{
private ngUnsubscribe = new Subject();
@ViewChild('modalError')
displayErrorRef: ModalComponent;
constructor(private errorService: ErrorService)
{
this.initializeErrors();
}
ngOnDestroy()
{
this.ngUnsubscribe.next();
this.ngUnsubscribe.complete();
}
private initializeErrors()
{
this
.errorService
.getErrors()
.pipe(takeUntil(this.ngUnsubscribe))
.subscribe((errors) =>
{
//this.displayErrorRef.error = errors
this.displayErrorRef.show();
});
}
}
ngUnsubscribe
是当你的主 app.component
被销毁时自动处理订阅。