[解決済み] AngularのHttpClientでエラーをキャッチする
質問
次のようなデータサービスがあります。
@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 {}
注 もし、あなたが 両方 エラーインターセプターとローカルなエラーハンドリングがある場合、当然ながらローカルなエラーハンドリングは発生しない可能性があります。 前に が、ローカルなエラー処理に到達する。
を実行します。 動作するデモ用プランカーはこちら .
関連
-
[解決済み] CLIを使ったAngular 2 - 制作のためのビルド
-
[解決済み] コンストラクタとngOnInitの違いについて
-
[解決済み] Angular HTMLバインディング
-
[解決済み] Angular:*ngClassを使った条件付きクラス
-
[解決済み] モジュール "@angular-devkit/build-angular" が見つかりませんでした。
-
[解決済み] 現在のルートを取得する方法
-
[解決済み] Angular CLI SASSオプション
-
[解決済み] ナンバーパイプ - Angular 2のパラメータは?
-
[解決済み] Angular 2 http.post()がリクエストを送信しない
-
[解決済み] Angularのルーターリンクが対応するコンポーネントにナビゲートされない
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Angularフレームワーク入門
-
[解決済み] オブジェクトのキーと値に*ngForでアクセスする
-
[解決済み] Angularの@Directiveと@Componentの比較
-
[解決済み] Angular 2のキープレスごとの変更イベント
-
[解決済み] 予算内の警告、初期値で最大値を超える
-
[解決済み] ngIf」は「div」の既知のプロパティではないため、バインドできない [重複] 。
-
[解決済み] Angularのルーティングされたコンポーネントにデータを渡すにはどうしたらいいですか?
-
[解決済み】コンポーネントのプロパティが現在の日付時間に依存している場合、Angular2の「expression has changed after it was checked」例外を管理する方法
-
[解決済み】エラー NG6002: AppModule の NgModule.imports に表示されるが、NgModule クラスに解決できなかった。
-
[解決済み] Angular 2+ - ベースのhrefを動的に設定する