如何从HttpErrorResponse获取请求的正文/内容? [Angular ErrorHandler]

时间:2018-11-14 02:19:26

标签: angular error-handling angular-errorhandler

假设我向服务器发送了一个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 });
                });
        }
    }
}

3 个答案:

答案 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调用中获取错误并不难。