代码之家  ›  专栏  ›  技术社区  ›  Alex Pappas

如何从httperrorresponse获取请求的正文/内容?[角度误差处理程序]

  •  0
  • Alex Pappas  · 技术社区  · 6 年前

    假设我发了一个 post 请求服务器创建用户。如果服务器响应错误,我想从 ErrorHandler 是的。原因是,例如,当“create user”失败时,我想显示一个通知,其中包含从表单中获取的一些详细信息,以及一个按钮,将您重定向回相应的页面,其中的字段再次填充了检索到的表单。

    这就是我 错误处理程序 看起来像:

    @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 回复  |  直到 6 年前
        1
  •  0
  •   Nick Wang    6 年前

    首先,必须确认在body中返回json错误。 下一步你可以为你的想法定制httpinterceptor,更多细节你可以通过关键字角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 }]
    

    告诉我对你是否合适:)

        2
  •  0
  •   Gabriel Lopez    6 年前

    我认为从httperrorresponse实例获取body是不可能的,因为它扩展了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;
        });
    
      }
    }
    

    然后将inteceptor添加到app.module中,如下所示:

    providers: [
        {provide: HTTP_INTERCEPTORS, useClass: ResponseInterceptor, multi: true}],
    
        3
  •  0
  •   Adam    6 年前

    我对加布里埃尔洛佩兹的回答有一个不同的看法,那就是拦截者:

    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);
              }
            })
          );
      }
    }
    

    和gabriel的回答一样,拦截器需要在app.module.ts中声明 providers 以下内容:

    @NgModule({
      providers: [
        {
          provide: HTTP_INTERCEPTORS,
          useClass: HttpErrorInterceptor,
          multi: true
        },
        ...
    

    我对此不满意,因为这可能意味着角度httpclient错误处理过于工程化。从rest api调用获取错误应该不难。