首页 > 解决方案 > 如何从 Angular 的 API 中获取错误消息?

问题描述

我正在使用 Angular 6,并且我有一项服务尝试通过发出 POST 请求在后端数据库中创建记录。我在这样的服务中实现了这个请求:

... usual imports and other Angular boiler plate omitted for brevity ...

export class SitesService {

  constructor(private http: HttpClient) {}

  addSite(siteName){
    const url = environment.apiUrl + '/api/v1/spi/sites/';
    const body = { 'name': siteName };

    const header = new HttpHeaders({'Content-Type':  'application/json' });
    return this.http.post(url, body, { headers: header }).pipe(map ( res => <Site>res ));
  }

我在我的组件代码中使用了上述服务:

... usual imports and Angular boiler plate omitted for brevity ...

export class SitesComponent implements OnInit {

  ... local variable declaration omitted ...

  constructor(private service: SitesService) {
       ... more unrelated code omitted ...


  addSite(siteName) {
    this.showLoader = true;
    this.service.addSite(this.siteName).subscribe(
      data => this.postSuccess(data),
      error => this.postError(error)
    );
  }

  private postError(error) {
      console.log('ERROR IS');
      console.log(error);
      ... omitted ...
  }

当 API 以 BAD REQUEST 400 响应时,我知道它提供了一条消息以及状态号 400。正如我在浏览器开发人员控制台中看到的那样:

在此处输入图像描述

但我的postError()方法所做的就是将这个写到控制台:

ERROR IS
Bad Request

我希望能够输出name: This field is required..

这是一个屏幕截图,显示我收到的是响应代码 400 而不是 200。

在此处输入图像描述

更新

事实证明,我团队中的某个人已经实现了拦截器。这是它的代码:(我添加了console.log's)。

import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import {LoginService} from '../login/login.service'



@Injectable()
export class ErrorInterceptor implements HttpInterceptor {
    constructor(private authenticationService: LoginService) {}
    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        return next.handle(request).pipe(catchError(err => {
          console.log('ErrirInterceptor err is:');
          console.log(err);
            if (err.status === 401) {
                // auto logout if 401 response returned from api
                this.authenticationService.logout();
            }
            const error = err.error.message || err.statusText;
            return throwError(error);
        }))
    }
}

当我访问麻烦的 api 时,console.log 的输出:

ErrirInterceptor err is:
error:
name: Array(1)
0: "This field is required."
...

但我仍然不明白如何将该错误消息发送给我的 SitesComponentSitesService班级。

更新二

事实证明,之前编写的拦截器没有处理 Django Generic Views 生成的错误响应,所以我通过更改这一行来更新它......

            const error = err.error.message || err.statusText;

...对此:

            const error = err.error.message || err.error.name || err.statusText;

标签: angular

解决方案


使用拦截器创建文件

import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpErrorResponse, HttpResponse } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import 'rxjs/add/operator/do';


@Injectable( {
    providedIn: 'root'
} )
export class YourInterceptor implements HttpInterceptor {
    constructor () { }

    intercept ( request: HttpRequest<any>, next: HttpHandler ): Observable<HttpEvent<any>> {

        return next.handle( request )
            .do( ( response: HttpEvent<any> ) => {
                if ( response instanceof HttpResponse ) {
                    for ( const key of response.headers.keys() ) {
                        console.log(key); // ***** The message should come out here ******
                    }
                }
            }, ( error: any ) => {
                if ( error instanceof HttpErrorResponse ) {
                    console.error( error );
                    console.error( error.status );
                }
            } );
    }
}

然后将其导入应用程序的主模块

import {
    YourInterceptor
} from './interceptors/.yourInterceptor';



    @NgModule( {
    declarations: [ . . . ],
    imports: [ . . . ],
    providers: [
        {
            provide: HTTP_INTERCEPTORS,
            useClass: YourInterceptor,
            multi: true
        }
    ],
    bootstrap: [ . . . ]
} )

推荐阅读