假设我向服务器发送了一个post
请求,以创建一个用户。如果服务器响应错误,我想从ErrorHandler
获取我提交(附加到该请求)的正文(表单)。这样做的原因是,例如,当“创建用户”失败时,我想显示一个通知,其中包含从表单中获取的一些详细信息,以及一个按钮,用于将您重定向回相应的页面,并使用检索到的字段再次填充字段表格。
这是我的ErrorHandler
的样子:
@Injectable()
export class ErrorsHandler implements ErrorHandler {
constructor(
private injector: Injector,
) { }
handleError(error: Error | HttpErrorResponse) {
const errorsService = this.injector.get(ErrorsService);
const router = this.injector.get(Router);
const zone = this.injector.get(NgZone);
if (error instanceof HttpErrorResponse) {
// Server error happened
if (!navigator.onLine) {
return console.log('No Internet Connection.');
}
else if (error.status === HttpStatus.UNAUTHORIZED) {
console.log('ErrorsHandler handled HttpStatus Unauthorized. Navigating back to \'/login\' page.');
zone.run(() => router.navigate(['/login']));
}
else {
// Http Error
//How do I get the form from here? I need it for user notification.
return console.log('%c SERVER ERROR ', 'background: #222; color: #ff6961 ; font-size: 15px; border: 2px solid #ff6961;', error);
}
} else {
// Client Error Happend
// Send the error to the server and then
// redirect the user to the page with all the info
errorsService
.log(error)
.subscribe(errorWithContextInfo => {
router.navigate(['/error'], { queryParams: errorWithContextInfo });
});
}
}
}
答案 0 :(得分:0)
首先,必须确认正文中返回BE JSON错误。 下一步,您可以为您的想法自定义HttpInterceptor,可以通过关键字angular httpinterceptor搜索更多详细信息。
这是我的HttpInterceptor的来源,可能会有帮助。
import { Injectable } from '@angular/core';
import { HttpRequest, HttpInterceptor, HttpHandler, HttpEvent, HttpResponse } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { tap, catchError } from 'rxjs/operators';
@Injectable()
export class SiteHttpInterceptor implements HttpInterceptor {
constructor(
) {}
intercept(request: HttpRequest<any>, httpHandler: HttpHandler): Observable<any> {
let token = localStorage.getItem('token');
if (('/api/users/token').indexOf(request.url) < 0 && token) {
request = request.clone({
setHeaders: {
'authorization': 'bearer ' + token,
'Authenticationtoken': 'bearer ' + token
}
});
}
return httpHandler.handle(request).pipe(
tap((event: HttpEvent<any>) => {
//success
},
(err: any) => {
//error
}),
catchError(err => {
if (err.status === 401) {
// if you want to do sth. when 401 can code here
} else {
// other
}
return throwError(err);
})
);
}
}
,然后将HttpInterceptor设置为app.module.ts
import { SiteHttpInterceptor } from './providers/http-interceptor';
@NgModule({
providers: [{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy }]
让我知道您是否可以:)
答案 1 :(得分:0)
我认为从HttpErrorResponse实例获取主体是不可能的,因为它扩展了HttpResponseBase,而后者没有正常的HttpResponse那样具有body属性。
export declare class HttpErrorResponse extends HttpResponseBase implements Error {
readonly name: string;
readonly message: string;
readonly error: any | null;
/**
* Errors are never okay, even when the status code is in the 2xx success range.
*/
readonly ok: boolean;
constructor(init: {
error?: any;
headers?: HttpHeaders;
status?: number;
statusText?: string;
url?: string;
});
}
我要做的是使用响应感受器:
import { Injectable } from '@angular/core';
import { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { ResponseBusiness } from '../Models/General/ResponseBusiness.model';
import { MsgService } from '../services/msg.service';
import { AlertService } from '../services/alert.service';
@Injectable()
export class ResponseInterceptor implements HttpInterceptor {
constructor(private _msg: MsgService, private _alertService: AlertService) {
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req).map(resp => {
const response = <HttpResponse<ResponseBusiness<Object>>> resp;
if (resp instanceof HttpResponse) {
}
/* do whatever you need with the req.body */
if (resp instanceof HttpErrorResponse) {
const body = JSON.parse(req.body);
if (body && body.avoidMsg) {
return resp;
}
}
if (response.status === 200 && !response.body.result.status) {
this._msg.setMsg({message: `${response.body.result.codeNumber} ${response.body.result.codeDescription}`, tipo: 'error'});
}
return resp;
});
}
}
然后像下面这样将inceptceptor添加到您的app.module中:
providers: [
{provide: HTTP_INTERCEPTORS, useClass: ResponseInterceptor, multi: true}],
答案 2 :(得分:0)
我对@GabrielLopez的答案有一个拦截器:
{
"id": string,
"token": string,
"type": string,
"address": string,
"params": {
"ttl": string
}
}
就像加百利的回答一样,拦截器需要在app.module.ts import {Injectable} from '@angular/core';
import {HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpResponse}
from "@angular/common/http";
import {Observable, throwError} from "rxjs";
import {catchError, tap} from "rxjs/operators";
@Injectable()
export class HttpErrorInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>,
next: HttpHandler):
Observable<HttpEvent<any>> {
return next.handle(req)
.pipe(
tap((ev: HttpEvent<any>) => {
if (ev instanceof HttpResponse) {
console.log(`processing response ${ev.status}`);
}
}),
catchError(response => {
console.log('Processing http error', response);
if (response.error) {
return throwError(response.error);
} else if (response.message) {
return throwError(response.message);
} else {
return throwError(response);
}
})
);
}
}
中声明:
providers
对此我不满意,因为这可能意味着Angular HttpClient错误处理过度。从REST API调用中获取错误并不难。