web-dev-qa-db-ja.com

別のオブザーバブルの値を使用してオブザーバブルをフィルタリングする

私には2つのオブザーバブルがあります。

  1. チェックボックス入力のリストを表すオブザーバブル。
  2. サーバーからのイベントのストリームを表すオブザーバブル。

最初のものからの値を使用して2番目のオブザーバブルをフィルター処理したいと思います。

サーバーから受信した値には、チェックボックスリストの値に対応するtagプロパティが含まれます。上記の2つの組み合わせの結果であるオブザーバブルは、tagプロパティがチェックされたチェックボックスのセットに含まれているサーバーからの値のみを生成します。

30
Ionuț G. Stan

withLatestFrom を使用できます。 enter image description here

source.withLatestFrom(checkboxes, (data, checkbox) => ({data, checkbox}))
  .filter(({data, checkbox}) => ...)

ここで、checkboxesは、チェックボックス入力のリストを表すオブザーバブルです。 sourceは、サーバーからのイベントのストリームを表すオブザーバブルです。フィルター機能では、チェックボックスの設定と比較してデータが有効かどうかを確認し、それを通過させることができます。

ストリームが何かを放出する前に、checkboxesが少なくとも1つの値を放出することが重要であることに注意してください。

Ps。他の回答に関しては、ソースが cold であっても、このソリューションは機能します。

32
Dorus

ストリームBの値を使用してストリームAをフィルター処理するには、ストリームBを監視し、最新の値を使用してストリームAをフィルター処理する必要があります。

switch() を使用して、Bオブザーバブルをオブザーバブルに変換し、Aオブザーバブルから値を生成します。

_checkedInputValuesSource
    .map(function (options) {
        return dataSource
            .filter(function (value) {
                return options.indexOf(value) !== -1;
            });
    })
    .switch()
    .subscribe(function (x) {
        console.log('out: ' + x);
    });
_

switch()を使用すると、dataSourcehot observable であると想定されます。

interval()を使用してダミーデータを生成する例:

_var input,
    checkedInputValuesSource,
    dataSource;

input = document.querySelectorAll('input');

// Generate source describing the current filter.
checkedInputValuesSource = Rx.Observable
    .fromEvent(input, 'change')
    .map(function () {
        var inputs = document.querySelectorAll('input'),
            checkedInputValues = [];
        
        [].forEach.call(inputs, function (e) {
            if (e.checked) {
                checkedInputValues.Push(e.value);
            }
        });
        
        return checkedInputValues;
    })
    .startWith([]);

// Generate random data source (hot).
dataSource = Rx.Observable
    .interval(500)
    .map(function () {
        var options = ['a', 'b', 'c'];
    
        return options[Math.floor(Math.floor(Math.random() * options.length))];
    })
    .do(function (x) {
        console.log('in: ' + x);
    })
    .share();

checkedInputValuesSource
    .map(function (options) {
        return dataSource
            .filter(function (value) {
                return options.indexOf(value) !== -1;
            });
    })
    .switch()
    .subscribe(function (x) {
        console.log('out: ' + x);
    });_
_<script src='https://rawgit.com/Reactive-Extensions/RxJS/v.2.5.3/dist/rx.all.js'></script>

<input type='checkbox' value='a'>
<input type='checkbox' value='b'>
<input type='checkbox' value='c'>_

この例では、次のような出力が生成されます。

_in: c
in: a
out: a
in: b
in: c
out: a
in: b
in: a
_

ここで、inは生成されたすべての入力を反映し、bはフィルターを通過するデータを反映します。フィルターは、チェックボックスの入力をチェックすることで調整され、値「a」、「b」、「c」を反映します。

6
Gajus

どうやら、私が必要としたのは、selectfilterswitchLatestの組み合わせでした。これを示す小さなテストケースを書きました: https://Gist.github.com/igstan/d5b8db7b43f49dd87382#file-observable-filter-observable-js-L36-L45

2
Ionuț G. Stan