ニーズに応じて、いくつかのオプションがあります。リクエストごとにエラーを処理する場合は、リクエストにを追加catch
します。グローバルソリューションを追加する場合は、を使用しますHttpInterceptor
。
以下のソリューションのデモプランカーを開きます。
tl; dr
最も単純なケースで.catch()
は.subscribe()
、次のようにa またはを追加するだけです。
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)
);
しかし、これにはさらに詳細があります。以下を参照してください。
メソッド(ローカル)ソリューション:エラーをログに記録し、フォールバック応答を返す
1か所のみでエラーを処理する必要がある場合は、catch
完全に失敗するのではなく、デフォルト値(または空の応答)を使用して返すことができます。また.map
、キャストする必要はありません。ジェネリック関数を使用できます。出典:Angular.io-Getting Error Details。
したがって、ジェネリック.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 {}
注:エラーインターセプターと一部のローカルエラー処理の両方がある場合、当然、エラーはローカルエラー処理に到達する前にインターセプターによって常に処理されるため、ローカルエラー処理はトリガーされない可能性があります。
ここで動作するデモプランカーを実行します。
return this.httpClient.get<type>(...)
。そして、catch...
彼が実際にそれを消費するサービスのどこかにそれがあるのは、それが彼がオブザーバブルを構築する場所であり、それが流れを最もよく処理できるからです。