過去記事インデックス
- Reactive Extensions再入門 その1
- Reactive Extensions再入門 その2「IObservableインターフェースとIObserverインターフェース」
- Reactive Extensions再入門 その3「IObservableのファクトリメソッド」
- Reactive Extensions再入門 その4「Timer系のファクトリメソッド」
- Reactive Extensions再入門 その5「HotとCold」
- Reactive Extensions再入門 その6「HotなIObservableを作成するファクトリ」
- Reactive Extensions再入門 その7「LINQスタイルの拡張メソッド」
- Reactive Extensions再入門 その8「SkipとTakeメソッド」
- Reactive Extensions再入門 その9「Skip + Take + Repeat = ドラッグ」
- Reactive Extensions再入門 その10「Doメソッド」
- Reactive Extensions再入門 その11「Catchメソッド」
- Reactive Extensions再入門 その12「Finallyメソッドとリソース解放」
- Reactive Extensions再入門 その13「最後の値を取得するLatestとMostRecentメソッド」
- Reactive Extensions再入門 その14「Nextメソッド」
- Reactive Extensions再入門 その15「To*****系メソッド」
- Reactive Extensions再入門 その16「最大、最少、平均を求めるメソッド」
- Reactive Extensions再入門 その17「集計するメソッド」
- Reactive Extensions再入門 その18「CountメソッドとLongCountメソッド」
- Reactive Extensions再入門 その19「AnyメソッドとAllメソッド」
- Reactive Extensions再入門 その20「GroupByメソッドでグルーピングしてみよう」
- Reactive Extensions再入門 その21「GroupByUntilメソッド」
- Reactive Extensions再入門 その22「単一の値を取得するメソッド」
- Reactive Extensions再入門 その23「重複を排除するメソッド」
- Reactive Extensions再入門 その24「単一の値を取得するメソッド その2」
- Reactive Extensions再入門 その25「値をまとめるBufferメソッド」
- Reactive Extensions再入門 その26「値をまとめるWindowメソッド」
- Reactive Extensions再入門 その27「時間でフィルタリング?Sampleメソッド」
- Reactive Extensions再入門 その28「落ち着いたら流すThrottleメソッド」
- Reactive Extensions再入門 その29「値を指定した時間だけ遅延させるDelayメソッド」
- Reactive Extensions再入門 その30「もう待ちきれない!を表現するTimeoutメソッド」
- Reactive Extensions再入門 その31「時間に関する情報を付与するTimestampとTimeIntervalメソッド」
- Reactive Extensions再入門 その32「型変換を行うCastとOfTypeメソッド」
- Reactive Extensions再入門 その33「シーケンスの最後を起点にSkipとTake」
はじめに
今回は、エラーに対応するためのメソッドの1つOnErrorResumeNextというメソッドについてみていきます。
OnErrorResumeNextメソッド
ここでは、OnErrorResumeNextメソッドについて説明します。このメソッドはIObservable
コード例を下記に示します。
Observable // 例外を出す .Throw<string>(new Exception()) // OnErrorResumeNextでエラーになったときの代わりを指定しておく .OnErrorResumeNext(Observable.Return("OK")) // 購読 .Subscribe( s => Console.WriteLine("OnNext: {0}", s), ex => Console.WriteLine("OnError: {0}", ex), () => Console.WriteLine("OnCompleted"));
最初にThrowメソッドを使って例外を発生させています。それに対してOnErrorResumeNextメソッドを使ってOKという文字列を流し込んでいます。実行結果を以下に示します。
OnNext: OK OnCompleted
Throwメソッドで発生された例外は、Subscribeまで届いていないことが確認できます。このように例外発生時に、別のIObservable
OnErrorResumeNextは、IObservable
public static IObservable<T> OnErrorResumeNext<T>(this IEnumerable<IObservable<T>> sources); public static IObservable<T> OnErrorResumeNext<T>(params IObservable<T>[] sources);
このメソッドを使うと、最初のIObservable
// 4番目にOK new[] { "NG", "Error", "Abort", "OK" } // インデックスと値のペアに変換 .Select((s, i) => new { index = i, value = s }) // OK以外は例外を飛ばすIO<string>を返す(IEnumerable<IObservable<T>>へ変換) .Select(s => s.value != "OK" ? Observable.Throw<string>(new Exception(s.ToString())) : Observable.Return(s.ToString())) .OnErrorResumeNext() // 購読 .Subscribe( s => Console.WriteLine("OnNext: {0}", s), ex => Console.WriteLine("OnError: {0}", ex), () => Console.WriteLine("OnCompleted"));
多少複雑ですが、{“NG”, “Error”, “Abort”, “OK”}という文字列の配列から、IEnumerable
OnNext: { index = 3, value = OK } OnCompleted
NGやError, Abortの文字列から生成される例外は全て無視してOKがSubscribeに渡ってきていることが確認できます。動作確認のためOKの文字列の場所を下記のように2番目にくるように書き直します。
// 2番目にOK new[] { "NG", "OK", "Abort", "Error" } // インデックスと値のペアに変換 .Select((s, i) => new { index = i, value = s }) // OK以外は例外を飛ばすIO<string>を返す(IEnumerable<IObservable<T>>へ変換) .Select(s => s.value != "OK" ? Observable.Throw<string>(new Exception(s.ToString())) : Observable.Return(s.ToString())) .OnErrorResumeNext() // 購読 .Subscribe( s => Console.WriteLine("OnNext: {0}", s), ex => Console.WriteLine("OnError: {0}", ex), () => Console.WriteLine("OnCompleted"));
実行結果を以下に示します。
OnNext: { index = 1, value = OK } OnCompleted
今度はindexが1になっていることが確認できます。全て例外で終わった場合(このプログラム例では最初の文字列の配列にOKが無い場合)は以下のようにOnCompletedになります。
OnCompleted
これまでのサンプルではOnErrorResumeNextの挙動を確認するために単純なプログラムを書いていましたが、このメソッドを使うと例えば、プライマリのサーバに対して非同期にデータを要求して例外が発生した場合にはセカンダリのサーバに対してデータを要求するというプログラムを書くことができます。