我正在处理四个部分的错误......服务器返回错误的 http 拦截器,一个基于内置 Angular 错误处理程序的全局错误处理程序。将错误记录到后端服务以提供支持的错误服务以及用于向最终用户显示友好消息的 Material 对话框组件。
有一些错误我们希望捕获错误状态代码并重定向到组件以获得更友好的最终用户体验。
一个例子是 404。我们有一个未找到的组件。如果服务器错误状态为 404,我想重定向到未找到的组件并且不显示错误对话框。
这是我的拦截器...
import { Injectable } from '@angular/core';
import {
HttpEvent,
HttpInterceptor,
HttpHandler,
HttpRequest,
HttpErrorResponse
} from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { retry, catchError } from 'rxjs/operators';
import { MatDialog } from '@angular/material';
import * as StackTrace from 'stacktrace-js';
import { ErrorDialogComponent } from './error-dialog.component';
import { PathLocationStrategy } from '@angular/common';
import { ErrorService } from './error.service';
import { LoggerService } from './logger.service';
import { Router } from '@angular/router';
@Injectable()
/**
* HttpErrorInterceptor to grab errors during http calls and log them
*
* @param (clientId) client id
*/
export class HttpErrorInterceptor implements HttpInterceptor {
/**
* constructor to grab errors during http calls and log them
*
* @param (dialog) MAT dialog to display to end user
* @param (errorService) error service to grab error messages
* @param (logger) logger service to post log errors to api and mantis
*/
constructor(
public dialog: MatDialog,
private errorService: ErrorService,
private logger: LoggerService,
private router: Router
) {}
/**
* Interecept to grab request, deal with it and pass it along
*
* @param (request) http request
* @param (next) send request to next http handler
*/
intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
// return the next statement
return next.handle(request).pipe(
// retry the call once
retry(1),
// catch the error
catchError((error: HttpErrorResponse) => {
if (error.status === 404) {
console.log('error.status: ', error.status);
// this.router.navigate(['']);
} else {
// Message variable to hold error message
let errorMessage = '';
// Variable to hold url location of error
const url =
location instanceof PathLocationStrategy ? location.path() : '';
// server-side error
errorMessage = this.errorService.getServerMessage(error);
// get the stack trace, lets grab the last 10 stacks only
StackTrace.fromError(error).then(stackframes => {
const stackString = stackframes
.splice(0, 20)
.map(function(sf) {
return sf.toString();
})
.join();
/**
* Function to log errors to api and mantis
*
* @param (errorMessage) error message passed to function
* @param (url) url passed to function
* @param (stackString) stackString passed to function
*/
this.logger
.createErrorLog(errorMessage, url, stackString)
.subscribe(
result => {
console.log('log filed: ', result);
},
(err: any) => console.log(err)
);
});
// Check if error is undefined and open dialog with appropriate error info
if (typeof errorMessage !== 'undefined') {
this.openDialog(errorMessage);
} else {
this.openDialog('undefined');
}
// throw error
return throwError(errorMessage);
}
})
);
}
/**
* Function to open dialog to display error
*
* @param (data) error data to display
*/
openDialog(data): void {
// Constant to hold and call dialog to display error
const dialogRef = this.dialog.open(ErrorDialogComponent, {
width: '60%',
data: data
});
// Code to run after the dialog is closed
dialogRef.afterClosed().subscribe(result => {
// Redirect back to home (dashboard)?
});
}
}
如您所见,我有一个简单的 if 我在哪里检查状态码。然后我有一个导航方法调用,我试图路由到任何内容,因为我的路由器模块有未找到的组件列为“无”路由。
这是重定向,但也显示错误对话框消息。我不希望这样显示。该对话框仅向最终用户显示错误消息,并为他们提供联系我们的方式。
这是我的全局处理程序...
import { ErrorHandler, Injectable, Injector } from '@angular/core';
import {
HttpErrorResponse,
HttpHeaders,
HttpClient
} from '@angular/common/http';
import { LocationStrategy, PathLocationStrategy } from '@angular/common';
import { throwError } from 'rxjs';
import * as StackTrace from 'stacktrace-js';
import { LoggerService } from '../core/logger.service';
import { ErrorService } from '../core/error.service';
import { MatDialog } from '@angular/material';
import { ErrorDialogComponent } from './error-dialog.component';
import { ConfigService } from '../app-config.service';
@Injectable({
providedIn: 'root'
})
/**
* GlobalErrorHandler to grab errors and log them
*/
export class GlobalErrorHandler implements ErrorHandler {
/**
* constructor to inject
*/
constructor(private injector: Injector, public dialog: MatDialog) {}
/**
* Function to handle errors
*
* @param (error) error passed to function
*/
handleError(error: Error) {
console.log('error (global): ', error);
const errorService = this.injector.get(ErrorService);
const logger = this.injector.get(LoggerService);
const location = this.injector.get(LocationStrategy);
// Message variable to hold error message
let errorMessage;
// Variable to hold url location of error
const url = location instanceof PathLocationStrategy ? location.path() : '';
console.log('url: ', url);
// check if error is a client error
if (error instanceof Error) {
// Client error message from error service
errorMessage = errorService.getClientMessage(error);
// Open dialog and display error message
this.openDialog(errorMessage);
}
// get the stack trace, lets grab the last 10 stacks only
StackTrace.fromError(error).then(stackframes => {
const stackString = stackframes
.splice(0, 20)
.map(function(sf) {
return sf.toString();
})
.join();
/**
* Function to log errors to api and mantis
*
* @param (errorMessage) error message passed to function
* @param (url) url passed to function
* @param (stackString) stackString passed to function
*/
logger.createErrorLog(errorMessage, url, stackString).subscribe(
result => {
console.log('log filed');
},
(err: any) => console.log(err)
);
});
return throwError(error);
}
/**
* Function to open dialog to display error
*
* @param (data) error data to display
*/
openDialog(data): void {
const dialogRef = this.dialog.open(ErrorDialogComponent, {
width: '60%',
data: data
});
// Code to run after the dialog is closed
dialogRef.afterClosed().subscribe(result => {
// Redirect back to home (dashboard)?
});
}
}
那么有没有办法捕获 404 代码并执行重定向,但不调用全局错误处理程序?
最佳答案
在 Z.Bagley 和他分享的链接的帮助下,我能够修复它。我注意到我错过了 next.handle() 调用。
这是我修改后的拦截器代码...
if (error.status === 404) {
const newRequest = request.clone();
return next.handle(newRequest);
}
关于javascript - 根据错误状态代码重定向到 Angular 中的组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60309408/