1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

.doと.subscribeの違い(SwiftとC#から見た)

Last updated at Posted at 2019-06-27

.doと.subscribeの違い

気になった記事の該当部分のコピペ抜粋です あとできっちりまとめる予定

Rx時代の先にあるもの

Rxの場合

do-swift.swift
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の要素に対しては何も加工を行ったりしません。コード例を下記に示します。

do-c#.cs
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メソッドのコード例を示す。

do-c#.cs
// 正常終了する場合 
// 実行結果: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メソッドを利用して実装すべきだろう。どうしてもそれらが利用できない場合は、法則を守るように注意深く実装する必要がある。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?