1. ホーム
  2. angular

[解決済み] AngularのHttpClientでエラーをキャッチする

2022-04-24 13:20:25

質問

次のようなデータサービスがあります。

@Injectable()
export class DataService {
    baseUrl = 'http://localhost'
        constructor(
        private httpClient: HttpClient) {
    }
    get(url, params): Promise<Object> {

        return this.sendRequest(this.baseUrl + url, 'get', null, params)
            .map((res) => {
                return res as Object
            })
            .toPromise();
    }
    post(url, body): Promise<Object> {
        return this.sendRequest(this.baseUrl + url, 'post', body)
            .map((res) => {
                return res as Object
            })
            .toPromise();
    }
    patch(url, body): Promise<Object> {
        return this.sendRequest(this.baseUrl + url, 'patch', body)
            .map((res) => {
                return res as Object
            })
            .toPromise();
    }
    sendRequest(url, type, body, params = null): Observable<any> {
        return this.httpClient[type](url, { params: params }, body)
    }
}

HTTPエラー(404など)が発生すると、嫌なコンソールメッセージが表示されるのですが。 ERROR Error: Uncaught (in promise)です。[object オブジェクト]。 から core.es5.js 私の場合、どのように処理すればいいのでしょうか?

どのように解決するのですか?

ニーズに応じて、いくつかのオプションがあります。もし、リクエストごとにエラーを処理したいのであれば、リクエストの前に catch をリクエストに追加してください。もしグローバルな解決策を加えたいのであれば HttpInterceptor .

開く 動作するデモ用プランカーはこちら をご覧ください。

tl;dr

最も単純なケースでは、単に .catch() または .subscribe() のような、です。

import 'rxjs/add/operator/catch'; // don't forget this, or you'll get a runtime error
this.httpClient
      .get("data-url")
      .catch((err: HttpErrorResponse) => {
        // simple logging, but you can do a lot more, see below
        console.error('An error occurred:', err.error);
      });

// or
this.httpClient
      .get("data-url")
      .subscribe(
        data => console.log('success', data),
        error => console.log('oops', error)
      );

しかし、これにはもっと詳細があり、以下をご覧ください。



方法(ローカル)解決策:エラーをログに記録し、フォールバック応答を返す

エラーを一箇所だけで処理する必要がある場合は catch で、完全に失敗するのではなく、デフォルト値 (あるいは空のレスポンス) を返します。また .map をキャストするだけで、汎用的な関数を使用することができます。ソースはこちら Angular.io - エラーの詳細を取得する .

そのため、一般的な .get() メソッドのようなものになります。

import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse } from "@angular/common/http";
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/of';
import 'rxjs/add/observable/empty';
import 'rxjs/add/operator/retry'; // don't forget the imports

@Injectable()
export class DataService {
    baseUrl = 'http://localhost';
    constructor(private httpClient: HttpClient) { }

    // notice the <T>, making the method generic
    get<T>(url, params): Observable<T> {
      return this.httpClient
          .get<T>(this.baseUrl + url, {params})
          .retry(3) // optionally add the retry
          .catch((err: HttpErrorResponse) => {

            if (err.error instanceof Error) {
              // A client-side or network error occurred. Handle it accordingly.
              console.error('An error occurred:', err.error.message);
            } else {
              // The backend returned an unsuccessful response code.
              // The response body may contain clues as to what went wrong,
              console.error(`Backend returned code ${err.status}, body was: ${err.error}`);
            }

            // ...optionally return a default fallback value so app can continue (pick one)
            // which could be a default value
            // return Observable.of<any>({my: "default value..."});
            // or simply an empty observable
            return Observable.empty<T>();
          });
     }
}

このエラーを処理することで、URLのサービスが悪い状態でもアプリを継続することができます。

このリクエストごとの解決策は、各メソッドに対して特定のデフォルトレスポンスを返したい場合に有効です。しかし、もしエラーの表示だけを気にするのなら (あるいはグローバルなデフォルトレスポンスが必要なら)、以下で説明するようにインターセプターを使用するのがよいでしょう。

を実行します。 動作するデモ用プランカーはこちら .



高度な使い方 すべてのリクエストまたはレスポンスを受信する

もう一度 Angular.ioガイド が表示されます。

の大きな特徴です。 @angular/common/http インターセプトとは、アプリケーションとバックエンドの間に位置するインターセプターを宣言する機能です。アプリケーションがリクエストを送ると、インターセプターはそれをサーバーに送る前に変換します。また、インターセプターは、アプリケーションがそれを見る前に、戻ってくる途中でレスポンスを変換することができます。これは、認証からロギングまであらゆる場面で役に立ちます。

これはもちろん、非常に簡単な方法でエラーを処理するために使用することができます ( デモプランカーはこちら ):

import { Injectable } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpResponse,
         HttpErrorResponse } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/of';
import 'rxjs/add/observable/empty';
import 'rxjs/add/operator/retry'; // don't forget the imports

@Injectable()
export class HttpErrorInterceptor implements HttpInterceptor {
  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(request)
      .catch((err: HttpErrorResponse) => {

        if (err.error instanceof Error) {
          // A client-side or network error occurred. Handle it accordingly.
          console.error('An error occurred:', err.error.message);
        } else {
          // The backend returned an unsuccessful response code.
          // The response body may contain clues as to what went wrong,
          console.error(`Backend returned code ${err.status}, body was: ${err.error}`);
        }

        // ...optionally return a default fallback value so app can continue (pick one)
        // which could be a default value (which has to be a HttpResponse here)
        // return Observable.of(new HttpResponse({body: [{name: "Default value..."}]}));
        // or simply an empty observable
        return Observable.empty<HttpEvent<any>>();
      });
  }
}

インターセプターを提供する。 を宣言するだけです。 HttpErrorInterceptor 上記のようにしても、アプリがそれを使うようになるわけではありません。必要なのは は、アプリのモジュール内で配線します。 をインターセプターとして提供することで、以下のようになります。

import { NgModule } from '@angular/core';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { HttpErrorInterceptor } from './path/http-error.interceptor';

@NgModule({
  ...
  providers: [{
    provide: HTTP_INTERCEPTORS,
    useClass: HttpErrorInterceptor,
    multi: true,
  }],
  ...
})
export class AppModule {}

もし、あなたが 両方 エラーインターセプターとローカルなエラーハンドリングがある場合、当然ながらローカルなエラーハンドリングは発生しない可能性があります。 前に が、ローカルなエラー処理に到達する。

を実行します。 動作するデモ用プランカーはこちら .