.doと.subscribeの違い(SwiftとC#から見た)
.doと.subscribeの違い
気になった記事の該当部分のコピペ抜粋です あとできっちりまとめる予定
・Rx時代の先にあるもの
Rxの場合
incrementCount
.do { increment in self.counter2 += increment } // 1
.map { increment in increment * 2 } // 2
.do { self.updateDatabase() } // 3
.subscribe { newIncrement in // 4
self.counter += newIncrement
}
do
自分の外の状態(Counter2)を変更する分かりにくいクロージャ
map
引数の値を2倍にして返すだけ。それ以外に余計なこと(クロージャ外の状態変えたり)しない分かりやすいクロージャ
do
データベースを操作しローカルの環境を大きく変える分かりにくいクロージャ
subscribe
自分の外の状態(Counter)を変更する分かりにくクロージャ
Rxでは登録したクロージャは分かりやすいもの、そうでないもの、明確な区別なくObserver
に保持されます。また今回はmap
を分かりやすいクロージャにしましたが、
map
内でスコープの広い状態の変更やデータベース操作などをすることで、分かりにくいクロージャにすることもできます。この辺は制約が無いため、Rxを使う人によってかなり幅がでます。
・Reactive Extensions再入門 その10「Doメソッド」
Doメソッド
DoメソッドはIObservableから発行された値を受けて処理を行うだけのメソッドです。5.4.1のDrag処理でも使用しましたが、要素を受け取って処理を行いIObservableの要素に対しては何も加工を行ったりしません。コード例を下記に示します。
var subject = new Subject<int>();
subject
// 途中に処理を挟む
.Do(i => Console.WriteLine("Do : {0}", i))
// 購読(購読しないとOnNextをしても値が流れないね)
.Subscribe(i => Console.WriteLine("OnNext : {0}", i));
// 値の発行
subject.OnNext(1);
subject.OnNext(2);
subject.OnNext(3);
このコードを実行すると、Subscribeで値を購読している処理の前にDoの処理が行われていることが確認出来ます。
Do : 1
OnNext : 1
Do : 2
OnNext : 2
Do : 3
OnNext : 3
・連載:Reactive Extensions(Rx)入門 | 第2回 イベント・プログラミングとRx
IObserverオブジェクトの詳細
最初の「同じ実行結果のRxとforeach文のコード」の例ではIObserverインターフェイスのメンバのうち、OnNextメソッドのデリゲートしか記述していなかった。このOnNextは、値がオブザーバに届くたびに実行されるメソッドで、最も利用されるものだろう。残りの2つのうち、OnErrorは例外発生時に実行されるメソッド、OnCompletedはシーケンスが完了後に実行されるメソッドを表す。これら3つのメソッドのデリゲートを指定する場合の、Subcribeメソッドのコード例を示す。
// 正常終了する場合
// 実行結果:1, 2, 3, 4, 5, Completed
Observable.Range(1, 5)
.Subscribe(
x => Console.WriteLine(x),
ex => Console.WriteLine("Error"),
() => Console.WriteLine("Completed"));
// 途中で例外が発生する場合
// 実行結果:1, 2, Error
Observable.Range(1, 5)
.Do(x => { if (x == 3) throw new Exception(); })
.Subscribe(
x => Console.WriteLine(x),
ex => Console.WriteLine("Error"),
() => Console.WriteLine("Completed"));
do-vb.vb
' 正常終了する場合
' 実行結果:1, 2, 3, 4, 5, Completed
Observable.Range(1, 5).
Subscribe(
Sub(x) Console.WriteLine(x),
Sub(ex) Console.WriteLine("Error"),
Sub() Console.WriteLine("Completed"))
' 途中で例外が発生する場合
' 実行結果:1, 2, Error
Observable.Range(1, 5).
Do(Sub(x)
If (x = 3) Then
Throw New Exception()
End If
End Sub).
Subscribe(
Sub(x) Console.WriteLine(x),
Sub(ex) Console.WriteLine("Error"),
Sub() Console.WriteLine("Completed"))
OnError/OnCompletedメソッドのデリゲートを含めたSubcribeメソッドのコードの実行例(上:C#、下:VB)
Doメソッドはパイプラインを通過する値に処理を加えて、元の値はそのまま後続へ渡す。今回は値が「3」のときに例外を発生させるようにした。
上記のコードを実行した場合、Rangeメソッドにより「1」~「5」の値の生成が完了すると、OnCompletedメソッドが呼ばれる、もしくは途中で例外が発生するとOnErrorメソッドが呼ばれるのが確認できるだろう。なお、OnErrorメソッド、もしくはOnCompletedメソッドは、どちらか片方しか呼ばれることはない。つまり、OnErrorメソッドが呼ばれた後にOnCompletedメソッドが呼ばれたりすることはない。また、OnErrorメソッド、もしくはOnCompletedメソッドが呼ばれた後にOnNextメソッドが呼ばれることもない*3。
*3 この法則はRxに標準で用意されているメソッドではすべて守られている。また、メソッドを自作する場合でもObservable.CreateメソッドといったRx標準で用意されている生成メソッドを用いれば守られる。さらにSubscirbeメソッドの呼び出し時にもRxで用意されているObserver(前述のSystem.ObservableExtensionsクラスによる拡張メソッド、もしくはObserver.Createメソッド)を使えば自動的に守られるようになっている。このように、幾重にも渡って法則が厳守されるようになっているため、ほぼ100%この法則が破られることはないが、IObservable<T>/IObserver<T>オブジェクトをすべて一から自前で実装する場合は、この法則に反する挙動をする可能性もある。ただし、そのような実装はすべきではない。安全のためにも、IObservable<T>インターフェイスやIObserver<T>インターフェイスを実装する際は、極力、Rxに用意されているObservable.Create/Observer.Createメソッドを利用して実装すべきだろう。どうしてもそれらが利用できない場合は、法則を守るように注意深く実装する必要がある。
Author And Source
この問題について(.doと.subscribeの違い(SwiftとC#から見た)), 我々は、より多くの情報をここで見つけました https://qiita.com/koutEngineerK/items/89bb66dbf675311132c1著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .