web-dev-qa-db-ja.com

Angular2で、observableからのエラー応答をインターセプトしてエラーチャネルに渡す方法

APIサーバーとやり取りするサービスがあります。 myHttpPost(data)メソッドがあります。このメソッドは:

  1. angularのhttp.postをサーバーに呼び出します
  2. 応答のステータスが200の場合、応答のjsonコンテンツをサブスクライバーに提供します
  3. 応答のステータスが異なる場合、応答を処理し、処理されたエラーをサブスクライバーに提供します

私のメソッドの現在のバージョンは次のとおりです。

_postData(path: string, data: Object): Rx.Observable<any> {
    let json = JSON.stringify(data);
    return this.http.post(path, json)
        .map(res => res.json())
}
_

Mapはエラーではなく成功時にのみ呼び出されるため、これは上記のリストのポイント3を実行していません。以下を追加することでシーケンスを変更できます。

_.catch(error => {
    let myError = prepareErrorContent(error);
    return Rx.Observable.throw(myError);
});
_

次に、サブスクライバー(別のサービス)はmyErrorを受信します(大丈夫です)が、rxjsのドキュメントには、catch()メソッドについて次のように記載されています:」シーケンス。」しかし、シーケンスは正常に終了し、続行しないようにします。上記のようにcatch()を使用すると、サブスクライバからのpostData()への次の呼び出しは機能しません(http呼び出しを行う代わりにすぐに同じエラーを返します)。シーケンスが終了していないためだと思います。

どうやってするの?

[編集]これは、このサービスを使用する私のサブスクライバメソッドです。

_ this.jsonHttp.postData(path, data)
    .subscribe(
        struct => onNext(struct),
        error => {
            let message = this.jsonHttp.extractError(error);
            onError(message)
        },
        () => onComplete ? onComplete() : null
    );
_
11
camcam

実際、HTTPリクエストごとに処理チェーンが作成され、実行されます。応答を受信すると(成功とエラーの両方)、チェーンが完了します。

リクエストを2回実行する場合、それらの間にリンクはありません。両方の要求が同じ処理チェーンの一部である場合、いくつかのリンクを作成できます。たとえば、flatMapswitchMapなどの観測可能な演算子を使用する場合。サンプルを次に示します。

return this.http.get(...)
        .map(res => res.json())
        .flatMap(jsonData => {
          // Can leverage the result of the previous request 
          return this.http.get(...).map(res => res.json());
        });

エラーが発生すると、処理チェーンが壊れ、catch演算子が呼び出されます。関連するコールバックでオブザーバブルを返し、処理チェーンを継続できます。古典的なオブザーバブルまたはObservable.throwのあるエラーの可能性があります。 Angular2のHTTP要求のコンテキストでは、2xxとは異なるステータスコードの応答はエラーと見なされます。

Observable.throwを返すとき、サブスクライブ時に指定された2番目のコールバックが呼び出されます。別のオブザーバブルの場合、最初のコールバックが呼び出されます。例えば:

return this.http.get(...)
        .map(res => res.json())
        .catch(res => {
          // The error callback (second parameter) is called
          return Observable.throw(res.json());
          // The success callback (first parameter) is called
          // return Observable.of(res.json());
        });

認証ヘッダーなしでリクエストを実行する(ボタンをクリックする)plunkrを実装したため、401ステータスコードが受信されます。もう一度クリックすると、ヘッダーが追加されるため、200ステータスコードが受信されます。 2つの要求間に関係がないことを示すためです。

このplunkrを参照してください: https://plnkr.co/edit/5WwWpwjvQmJ4AlncKVio?p=preview

18