【UniRx】エラーハンドリング系のオペレータ #102
前回の成果
非同期処理のオペレータをまとめた。
今回やること
エラーハンドリング系のオペレータをまとめます。
- 前回の成果
- 今回やること
- 例外発生時に、例外を補足せずに処理を行う
- 例外発生時に、購読し直す
- 指定した型の例外の場合、購読し直す
- 例外発生時に、指定した回数、指定した間隔で購読し直す
- 例外発生時に、代わりのObservableを渡す
- 指定した型の例外発生時に、代わりのObservableを渡す
- Catch時にObservableを返さずにOnCompletedを発行
- 参考サイト様
例外発生時に、例外を補足せずに処理を行う
DoOnError
例外発生時にOnErrorメッセージを用いて処理を発生させます。
メッセージそのものは変更しません。
ソースコード
/// <summary> /// 例外発生時に、例外を補足せずに処理を行う /// </summary> private void ExtionDoOnError() { Observable .Range(0, 1) .Do(_ => throw new Exception()) .DoOnError(e => { Debug.Log("DoOnError : " + e); }) .Subscribe(x => { Debug.Log("OnNext : " + x); }, e => { Debug.Log("OnError : " + e); }, () => { Debug.Log("OnCompleted"); }); }
結果
DoOnErrorが発行され、SubscribeのOnErrorが発行されています。
例外発生時に、購読し直す
Retry
例外が発生したときに、指定した回数ストリームを再購読します。
ソースコード
/// <summary> /// 例外発生時に、Subscribeし直す /// </summary> private void ExcuteRetry() { Observable .Range(0, 1) .Do(_ => throw new Exception()) .DoOnError(e => Debug.Log("DoOnError : " + e)) // 3回繰り返す .Retry(3) .Subscribe(x => { Debug.Log("OnNext : " + x); }, e => { Debug.Log("OnError : " + e); }, () => { Debug.Log("OnCompleted"); }); }
結果
引数で3を指定しているので、3回購読し直されています。
なので、DoOnErrorが3回呼ばれています。
指定した型の例外の場合、購読し直す
OnErrorRetry
引数で例外を指定することができます。
指定した例外が来た場合に購読し直します。
ソースコード
public class ExceptionA : Exception { } public class ExceptionB : Exception { } /// <summary> /// OnErrorRetryの実行 /// </summary> private void ExcuteOnErrorRetry() { Debug.Log("------throw A------"); OnErrorRetryThrowError(new ExceptionA()); Debug.Log("------throw B------"); OnErrorRetryThrowError(new ExceptionB()); } /// <summary> /// 指定した型の例外の場合、Subscribeし直す /// </summary> private void OnErrorRetryThrowError(Exception error) { Observable .Range(0, 1) .Do(_ => throw error) .DoOnError(e => Debug.Log("DoOnError : " + e)) // ExceptionAが来た場合 .OnErrorRetry((ExceptionA e) => { Debug.Log("OnErrorRetry A"); }, 3) // ExceptionBが来た場合 .OnErrorRetry((ExceptionB e) => { Debug.Log("OnErrorRetry B"); }, 3) .Subscribe(x => { Debug.Log("OnNext : " + x); }, e => { Debug.Log("OnError : " + e); }, () => { Debug.Log("OnCompleted"); }); }
結果
ExceptionAが例外に来た場合とExceptionBの場合でログが異なるのがわかります。
例外発生時に、指定した回数、指定した間隔で購読し直す
DoOnError
第二引数に繰り返す回数を、第三引数にTimeSpanを指定することができます。
ソースコード
/// <summary> /// 指定した回数、指定した間隔でSubscribeし直す /// </summary> private void ExcuteOnErrorRetryTime() { Observable .Range(0, 1) .Do(_ => throw new Exception()) .DoOnError(e => Debug.Log("DoOnError : " + e)) // 指定した回数、指定間隔で実行 .OnErrorRetry((Exception e) => { Debug.Log("OnErrorRetry"); }, 3, TimeSpan.FromSeconds(1)) .Subscribe(x => { Debug.Log("OnNext : " + x); }, e => { Debug.Log("OnError : " + e); }, () => { Debug.Log("OnCompleted"); }); }
結果
引数で指定した1秒毎に、計3回購読し直しています。
3回購読した後にはOnErrorを発行しています。
例外発生時に、代わりのObservableを渡す
Catch
例外が発生した際に、その例外を処理して代わりのObservableを渡すことが出来ます。
ソースコード
/// <summary> /// 例外発生時に、代わりのObservableを渡す /// </summary> private void ExcuteCatch() { Observable .Range(0, 1) .Select(x => x.ToString()) .Do(_ => throw new Exception()) .Catch((Exception e) => { // エラー処理の実行 return Observable.Return("Catch"); }) .Subscribe(x => { Debug.Log("OnNext : " + x); }, e => { Debug.Log("OnError : " + e); }, () => { Debug.Log("OnCompleted"); }); }
結果
本来OnNextに渡されるはずだった"1"が来ずに、"Catch"が渡されています。
指定した型の例外発生時に、代わりのObservableを渡す
Catch
指定した型の例外が発生した際に、その例外を処理して代わりのObservableを渡すことが出来ます。
ソースコード
public class ExceptionA : Exception { } public class ExceptionB : Exception { } /// <summary> /// 指定した型をCatchの実行 /// </summary> private void ExcuteCatchTarget() { Debug.Log("------throw A------"); CatchThrowError(new ExceptionA()); Debug.Log("------throw B------"); CatchThrowError(new ExceptionB()); } /// <summary> /// 指定した型の例外発生時に、代わりのObservableを渡す /// </summary> private void CatchThrowError(Exception error) { Observable .Range(0, 1) .Select(x => x.ToString()) .Do(_ => throw error) // ExceptionAが来た場合 .Catch((ExceptionA e) => { return Observable.Return("Catch A"); }) // ExceptionBが来た場合 .Catch((ExceptionB e) => { return Observable.Return("Catch B"); }) .Subscribe(x => { Debug.Log("OnNext : " + x); }, e => { Debug.Log("OnError : " + e); }, () => { Debug.Log("OnCompleted"); }); }
結果
本来OnNextに渡されるはずだった"1"が来ずに、"Catch ○"が渡されています。
また、ExceptionAを例外として投げた場合にはAが、
ExceptionBを例外として投げた場合にはBが返って来ています。
Catch時にObservableを返さずにOnCompletedを発行
CatchIgnore
Catchしたときに、特に処理をせずにOnCompletedを呼びたい場合に使用します。
ソースコード
/// <summary> /// Catch時にObservableを返さずにOnCompletedを発行 /// </summary> private void ExcuteCatchIgnore() { Observable .Range(0, 1) .Select(x => x.ToString()) .Do(_ => throw new Exception()) .CatchIgnore((Exception e) => { Debug.Log("Catch Ignore : " + e); }) .Subscribe(x => { Debug.Log("OnNext : " + x); }, e => { Debug.Log("OnError : " + e); }, () => { Debug.Log("OnCompleted"); }); }
結果
すぐにOnCompletedが呼ばれています。
今回は以上になります。
ここまでご視聴ありがとうございました。