私は次のSOの質問をレビューしました: ホットおよびコールドオブザーバブルとは何ですか?
要約する:
それでも、暑いのか寒いのかは依然として混乱の元だと感じています。だからここに私の質問があります:
すべてのrxオブザーバブルはデフォルトでコールドですか(サブジェクトを除く)?
私は、イベントがホットなオブザーバブルの典型的なメタファーであることをよく読みますが、Rx.fromEvent(input, 'click')
はコールドオブザーバブル(?)であることも読みます。
コールドオブザーバブルをホットオブザーバブルに変換するRx演算子(publish
およびshare
を除く)はありますか?
たとえば、Rx演算子withLatestFrom
とどのように機能しますか? _cold$
_をどこかにサブスクライブされたコールドオブザーバブルにします。 sth$.withLatestFrom(cold$,...)
はホットなオブザーバブルになりますか?
または、sth1$.withLatestFrom(cold$,...), sth2$.withLatestFrom(cold$,...)
を実行し、_sth1
_および_sth2
_をサブスクライブすると、両方のsth
に常に同じ値が表示されますか?
_Rx.fromEvent
_はコールドオブザーバブルを作成すると思っていましたが、答えの1つで述べたように、そうではありません。しかし、私はまだこの動作に困惑しています: codepen.io/anon/pen/NqQMJR?editors=101 。異なるサブスクリプションは、同じオブザーバブルから異なる値を取得します。 click
イベントは共有されませんでしたか?
数か月後に元の質問に戻ってきましたが、その間に得た知識を共有したいと思いました。説明のサポートとして次のコードを使用します( jsfiddle ):
var ta_count = document.getElementById('ta_count');
var ta_result = document.getElementById('ta_result');
var threshold = 3;
function emits ( who, who_ ) {return function ( x ) {
who.innerHTML = [who.innerHTML, who_ + " emits " + JSON.stringify(x)].join("\n");
};}
var messages$ = Rx.Observable.create(function (observer){
var count= 0;
setInterval(function(){
observer.onNext(++count);
}, 1000)
})
.do(emits(ta_count, 'count'))
.map(function(count){return count < threshold})
.do(emits(ta_result, 'result'))
messages$.subscribe(function(){});
回答の1つで述べたように、オブザーバブルを定義すると、一連のコールバックとパラメーターの登録が行われます。データフローを開始する必要があり、それはsubscribe
関数を介して行われます。 (説明のために簡略化された)詳細なフローは、その後見つけることができます。
オブザーバブルはデフォルトではコールドです。オブザーバブルをサブスクライブすると、アップストリームのサブスクリプションチェーンが発生します。最後のサブスクリプションは、ソースを処理し、そのデータをオブザーバーに送信する関数の実行につながります。
そのオブザーバーは次のオブザーバーに順番に送信し、データのダウンストリームフローをシンクオブザーバーに送ります。次の簡略図は、2人のサブスクライバが同じオブザーバブルをサブスクライブするときのサブスクリプションとデータフローを示しています。
ホットオブザーバブルは、サブジェクトを使用するか、multicast
演算子(およびその派生物、下の注3を参照)を使用して作成できます。
内部のmulticast
演算子は、サブジェクトを使用して、接続可能なオブザーバブルを返します。オペレーターへのすべてのサブスクリプションは、内部サブジェクトへのサブスクリプションになります。 connect
が呼び出されると、内側のサブジェクトはアップストリームのobservableにサブスクライブし、データはダウンストリームに流れます。サブジェクトはサブスクライブされたオブザーバーのリストを内部で操作し、すべてのサブスクライブされたオブザーバーに着信データをマルチキャストします。
次の図は、状況をまとめたものです。
最後に、オブザーバーパターンとオペレーターの実装によって引き起こされるデータの流れを理解することが重要です。
たとえば、obs
がホットの場合、hotOrCold = obs.op1
はコールドですか、ホットですか?答えは何でも:
obs.op1
の購読者がいない場合、op1
を介してデータは流れません。ホットobs
のサブスクライバーがいた場合、それはobs.op1
がデータの一部を失う可能性があることを意味しますop1
がマルチキャストライクな演算子ではないと仮定すると、hotOrCold
に2回サブスクライブするとop1
に2回サブスクライブし、obs
からのすべての値はop1
。ノート :
Subject type | `Publish` Operator | `Share` operator ------------------ | --------------------------- | ----------------- Rx.Subject | Rx.Observable.publish | share Rx.BehaviorSubject | Rx.Observable.publishValue | shareValue Rx.AsyncSubject | Rx.Observable.publishLast | N/A Rx.ReplaySubject | Rx.Observable.replay | shareReplay
Update:参照してください 次の記事はこちらおよびそこ )レッシュ。
サブジェクトに関する詳細は、この他のSO質問: 異なるRxJSサブジェクトのセマンティクスは何ですか?
あなたの要約とリンクされた質問は両方とも正しいです、私は用語があなたを混乱させるかもしれないと思います。ホットとコールドのオブザーバブルを、それぞれアクティブとパッシブのオブザーバブルとして考えることを提案します。
つまり、アクティブ(ホット)オブザーバブルは、誰かがサブスクライブしているかどうかに関係なく、アイテムを放出します。標準的な例では、ボタンクリックイベントは誰かが聞いているかどうかに関係なく発生します。この区別は重要です。たとえば、ボタンをクリックしてからボタンクリックを(この順序で)登録すると、既に発生したボタンクリックは表示されないためです。
パッシブ(コールド)オブザーバブルは、サブスクライバーが存在するまで待機してからアイテムを発行します。誰かがイベントを聞いているまでクリックできないボタンを想像してください。これにより、常にすべてのクリックイベントが表示されます。
すべてのRxオブザーバブルはデフォルトで「コールド」(またはパッシブ)ですか?いいえ、たとえばRx.fromEvent(input, 'click')
はホット(またはアクティブ)オブザーバブルです。
また、
Rx.fromEvent(input, 'click')
はコールドオブザーバブル(?)
そうではありません。
コールドオブザーバブルをホットオブザーバブルに変えるRxオペレーターはいますか?
ホット(アクティブ)オブザーバブルをコールド(パッシブ)オブザーバブルに変える概念は次のとおりです。サブスクライブされていない間に発生するイベントを記録し、それらのアイテムを(さまざまな方法で)将来登場するサブスクライバーに提供する必要があります。これを行う1つの方法は、 Subject を使用することです。たとえば、ReplaySubject
を使用して、放出されたアイテムをバッファリングし、それらを将来のサブスクライバーにリプレイできます。
名前を付けた2つの演算子(publish
およびshare
)は両方とも、サブジェクトを内部的に使用してその機能を提供します。
Rx演算子
withLatestFrom
でどのように機能しますか? _cold$
_をサブスクライブ済みのコールドオブザーバブルにします。something$.withLatestFrom(cold$,...)
はホットなオブザーバブルになりますか?
something
がホットオブザーバブルの場合、はい。 something
がコールドオブザーバブルの場合、いいえ。 something
がボタンクリックイベントのストリームである場合、イベントの例に戻ります。
_var clickWith3 = Rx.fromEvent(input, 'click')
.withLatest(Rx.Observable.from([1, 2, 3]);
_
または、
foo$.withLatestFrom(cold$,...), bar$.withLatestFrom(cold$,...)
を実行し、foo
およびbar
をサブスクライブすると、両方に常に同じ値が表示されますか?
常にではない。繰り返しますが、たとえばfoo
とbar
が異なるボタンをクリックした場合、異なる値が表示されます。同様に、それらが同じボタンであっても、組み合わせ関数(withLatest
への2番目の引数)が同じ入力に対して同じ結果を返さない場合、同じ値は表示されません(なぜなら、以下で説明するように、2回呼び出されます)。
_
Rx.fromEvent
_はコールドオブザーバブルを作成すると思っていましたが、答えの1つで述べたように、そうではありません。ただし、この動作にはまだ困惑しています: codepen.io/anon/pen/NqQMJR?editors=101 。異なるサブスクリプションは、同じオブザーバブルから異なる値を取得します。click
イベントは共有されませんでしたか?
私は Enigmativityによるこの素晴らしい答え に私が同じ振る舞いについて持っていた質問を指摘します。その答えは、私ができるよりもずっとよく説明しますが、その要点は、ソース(クリックイベント)が「共有」されているということです。しかし、あなたの操作はそうではありません。クリックイベントだけでなく、その操作も共有する場合は、明示的に共有する必要があります。
コードペンのvalues
は怠laです-何かがサブスクライブするまで何も起こりません。サブスクライブすると、それが実行されて接続されます。したがって、この例では、同じ変数にサブスクライブしていますが、2つの異なるストリームを作成しています。サブスクライブ呼び出しごとに1つ。
values
は、click
が付加されたmap
のストリームのジェネレーターと考えることができます。
そのマップの最後にある.share()
は、暗黙的にサブスクライブしているため、予想される動作を作成します。