2013-07-19 5 views
15

У меня есть два наблюдаемые:Фильтр наблюдаемых с использованием значений из других наблюдаемых

  1. наблюдаемые, представляющих список входов флажка.
  2. Наблюдаемое представление потока событий, поступающих с сервера.

Я хотел бы отфильтровать вторую наблюдаемую, используя значения из первой.

Значения, полученные с сервера, включают в себя свойство tag, которое соответствует значениям в списке флажков. Наблюдаемое, полученное в результате комбинации указанных выше двух, приведет только к значениям от сервера, чье свойство tag включено в набор отмеченных флажков.

ответ

17

Вы можете использовать withLatestFrom. enter image description here.

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

Здесь checkboxes является наблюдаемым, представляющим список входов флажка. source является наблюдаемым, представляющим поток событий, поступающих с сервера. В функции фильтра вы можете проверить, действительно ли данные действительны по сравнению с настройками флажка и разрешить им прохождение.

Обратите внимание, что важно checkboxes излучает не менее 1 значения, прежде чем поток может испускать что-либо.

Ps. Что касается других ответов, это решение работает, даже если источником является cold.

+1

@ IonuţG.Stan Действительно. И это удивительно, сколько людей по-прежнему относятся к этим старым вопросам, поэтому, надеюсь, это поможет нескольким людям :) – Dorus

+0

Вы должны заметить, что это аннотируется с помощью @Experimental и может в любой момент изменить ** значительно **, поэтому он не должен использоваться или использоваться в производственном коде. – acrespo

+0

@acrespo Это используется в производственном коде во многих местах. Где именно вы нашли этот экспериментальный тег? – Dorus

2

По-видимому, мне нужна была комбинация select, filter и switchLatest. Я написал небольшой тестовый пример, демонстрирующий это: https://gist.github.com/igstan/d5b8db7b43f49dd87382#file-observable-filter-observable-js-L36-L45

+0

Чтобы быть ясным, ваш gist использует 'map' и' filter', которые я предполагаю, это просто псевдонимы, которые вы сделали для 'select' и' where'? – Brandon

+0

@Brandon да, это правда. –

+0

Привет, я хотел бы сыграть с вашим кодом в github, какие другие js libs мне нужны? – Guenni

4

Для того, чтобы фильтровать поток A с использованием значений потока B, вы должны наблюдать поток B и использовать последние значения для фильтрации потока А.

Использование 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() предполагает, что dataSource является hot 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».

+0

Разве это не то, что я написал в своем решении? –

+2

Может быть. Я просматриваю каждый вопрос/ответ rxjs и каждый раз вносил свой вклад. Ваш ответ ссылается на внешний ресурс и требует дополнительных зависимостей для запуска. Я записал решение в изолированной среде. – Gajus

+1

Обратите внимание, что вы можете выполнить эту работу, даже если источник холодный. С помощью ['publish (...)'] (https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/publish.md). Как это: 'DATASOURCE .publish (DSRC => checkedInputValuesSource .switchMap ((опции) => DSRC .filter ((значение) => options.indexOf (значение) == -1) ) !)' – Dorus

Смежные вопросы