7

他の「FRP」ライブラリとは異なり、Rx はグリッチ (時間の不一致データで呼び出されるコールバック) を防止しません。これを回避する良い方法はありますか?

例として、単一のストリームから派生した一連の高価な計算があるとします (たとえば、以下の _.identity の代わりに、並べ替えまたは ajax フェッチを行います)。高価なものの再計算を避けるために、distinctUntilChanged を実行します。

sub = new Rx.Subject();
a = sub.distinctUntilChanged().share();
b = a.select(_.identity).distinctUntilChanged().share();
c = b.select(_.identity).distinctUntilChanged();
d = Rx.Observable.combineLatest(a, b, c, function () { return _.toArray(arguments); });
d.subscribe(console.log.bind(console));
sub.onNext('a');
sub.onNext('b');

2 番目のイベントは、多数のグリッチ状態を引き起こすことになります。1 つではなく 3 つのイベントが発生するため、大量の CPU が浪費され、不一致のデータを明示的に回避する必要があります。

この特定の例は、distinctUntilChanged を削除し、入力が変更されていない場合に前の結果を通過するように不安定な scan() 関数を作成することで回避できます。次に、combineLatest を使用する代わりに、結果を圧縮できます。不器用ですが、実行可能です。

ただし、どこかに ajax 呼び出しなどの非同期性がある場合、zip は機能しません。ajax 呼び出しは同期 (キャッシュされている場合) または非同期で完了するため、zip は使用できません。

編集

より簡単な例で望ましい動作を明確にしようとしています:

a と b の 2 つのストリームがあります。b は a に依存します。b は非同期ですが、ブラウザはそれをキャッシュする可能性があるため、a とは独立して更新することも、a と同時に更新することもできます。したがって、ブラウザ内の特定のイベントによって、次の 3 つのいずれかが発生する可能性があります。b 更新; a と b の両方を更新します。望ましい動作は、コールバック (たとえば、render メソッド) を 3 つのケースすべてで 1 回だけ呼び出すことです。

a または b が単独で発火すると、zip からコールバックが得られないため、zip は機能しません。a と b が同時に起動すると、2 つのコールバックが発生するため、combineLatest は機能しません。

4

1 に答える 1