2017-11-03 2 views
0

私はAPI、C#クライアントとそのAPIラッパーを持っています。私は柔軟な方法でAPIを扱うための拡張メソッドを含むクラスを持っています。HttpResponseMessageの観測可能性の中でAPIエラーをチェックし、どのようにチェックするのですか?

エラーを処理しようとしています。これらの拡張メソッドの一つがある:

public static IObservable<HttpResponseMessage> CheckForApiErrors(this IObservable<HttpResponseMessage> source) 
{ 
    return source.SelectMany(message => { 
     if (message.IsSuccessStatusCode) { 
      return source; 
     } 

     var exTask = ApiException.CreateFromHttpMessage(message); 

     return Observable.FromAsync(() => exTask).SelectMany(Observable.Throw<HttpResponseMessage>); 
    }); 
} 

これは正しくスローし、私ができる観測可能に​​後で。ただし、そのメソッドを通過した(成功した)すべての要求が今再生されます。 私が/some_endpointに電話して成功すると、オブザーバブルが再生され、/some_endpointが再び呼び出されます。

return source.SelectMany(message => { 
    if (message.IsSuccessStatusCode) { 
     return source; // <----------- 
    } 

私は本当に、私はエラーをチェックし、スローするように私のSelectManyのアプローチについて疑うよcorrecltyとエラーをスローする方法を知りませんが、それはです:

私は障害のあるラインはここにあると思います私が見つけた唯一の解決策です。

throwDo()に入れて、通常のストリームに干渉しないようにしたいが、それは観測可能なアプリケーションだけでなく、アプリケーション全体をクラッシュさせる。

編集(会合を持って、それの真ん中にアイデアを持っていた今朝疲れでなければなりません):

代わりのreturn source;私はreturn Observable.Return(message);を行うことができます。もちろん、それは動作します。しかし、私はまだ私のアプローチが嫌いですが、私はまだそれを達成するよりエレガントな方法があるように感じています。

+2

"これは私が見つけた唯一の解決策です。" - ソースに2つのサブスクリプションが存在するため解決策ではありません。 Shlomoは正しいアプローチをとった。 – Enigmativity

答えて

3

ApiExceptionには、このような形のシグネチャがありますか?

public class ApiException 
{ 
    public static Task<Exception> CreateFromHttpMessage(HttpResponseMessage message) 
    { 
     return Task.FromResult(new Exception()); 
    } 
} 

あなたがException代わりのTask<Exception>を返却していた場合、それはよりまっすぐ進むだろう。いずれにせよ、いくつかの選択肢があります:

public static IObservable<HttpResponseMessage> CheckForApiErrors2(this IObservable<HttpResponseMessage> source) 
{ 
    return source.SelectMany(message => message.IsSuccessStatusCode 
     ? Observable.Return(message) 
     : Observable.FromAsync(() => ApiException.CreateFromHttpMessage(message)).SelectMany(Observable.Throw<HttpResponseMessage> 
    ) 
} 

public static IObservable<HttpResponseMessage> CheckForApiErrors3(this IObservable<HttpResponseMessage> source) 
{ 
    return source.Publish(_source => _source 
     .Where(message => message.IsSuccessStatusCode) 
     .Merge(_source 
      .Where(message => !message.IsSuccessStatusCode) 
      .SelectMany(message => Observable.FromAsync(() => ApiException.CreateFromHttpMessage(message)).SelectMany(Observable.Throw<HttpResponseMessage>)) 
     ) 
    ); 
} 

最初の選択肢はコードとほとんど同じですが、圧縮されています。 2番目のコードは、コードを2つのストリーム(成功と失敗)に分割し、別々に処理し、それらを再び一緒にマージします。

+0

ありがとう!はい、ApiException静的ファクトリは、メッセージの内容( '.ReadAsStringAsync()')から読み込むため、非同期です。あなたの最初の解決策は私の鉱山の凝縮版です(編集中)。私は、メソッドがより複雑になることを計画しています。三項が十分ではないので、Observable.Ifまたは三項を使用しませんでした。 2番目の解決策は面白いですが、もう少し不透明です。 少なくとも、私は不必要な複雑さを導入していないことを今知っているので、助けてくれてありがとう! –

関連する問題