2016-11-02 3 views
1

У меня есть интерфейс вроде этого:RxJs. Сочетание последних и один раз

enter image description here

Где я могу

  • Введите что-нибудь в поле поиска
  • Перетащите пользователей из таблицы картировать

Необходимая логика:

  • Первоначально диаграмма показывает некоторое подмножество всех пользователей (например, первые 10)
  • Когда пользователи затянулись на графике они будут добавлены к пользователям, которые уже есть
  • Когда фильтр применяются для всех пользователей удаляются из диаграммы и то он заселен некоторым подмножеством соответствующих пользователей.

Я пытаюсь реализовать такую ​​логику с помощью RxJs. У меня есть filteredUsers$ и addedUsers$ поток, который производит пользователей, соответствующих фильтру, и перетаскивает пользователей соответственно.

мне нужно объединить их таким образом:

 Observable 
      .<OPERATOR>(filteredUsers$, addedUsers$) 
      .subscribe(([filteredUsers, addedUsers]) => { 
       // When filteredUsers$ fires: 
       // filteredUsers is value from stream 
       // addedUsers == null 

       // When addedUsers$ fires: 
       // filteredUsers is latest available value 
       // addedUsers is value from stream 

       redrawChart(/* combining users */) 
      }); 

Любые идеи, как я могу добиться этого?

Время последовательности:

Filtered: - a - - - - a - -> 
Added : - - b - b - - - -> 
Result : - a ab - ab - a - -> 
+0

Возможно, вы ищете оператор «zip». – Brozorec

+0

@ Zozo, посмотрите на последовательность времени. Zip приведет к двум «ab» событиям. Но мне нужен другой выход. –

ответ

2

Если вы хотите, чтобы окончательный поток заселяться только тогда, когда AddUsers $ пожары с последним из может быть решение:

enter image description here

Итак, в вашем случае addUsers $ может быть первым потоком. Вы можете попробовать следующий код:

let firstObservable$ = Observable.from([1, 2, 3, 4]) 
    .zip(Observable.interval(50), (a, b) => { 
     return a; 
    }); 

    let secondObservable$ = Observable.from([5, 6]) 
    .zip(
     Observable.interval(70), (a, b) => { 
     return a; 
     }); 

    firstObservable$ 
    .withLatestFrom(secondObservable$, (f, s) => ({ a: f, b: s })) 
    .subscribe(x => { 
     console.log('result: ', x); 
    }); 

Первая наблюдаемая Издает каждые 50 мс значение из массива. Второй наблюдаемый каждые 75 мс.

Значения напечатанных являются {а: 2, б: 5} {а: 3, б: 6} {а: 4, б: 6}

Поскольку 1 излучается прежде, чем 5 мы теряем пару (1,5)!

Я не понимаю, но пропуская пару из addUsers $, если другой поток не выбрал, может быть нежелательным для вас. Вы можете преодолеть это, если вы начнете второй поток с начальным значением и затем отфильтровываете любые результаты, которые вы не хотите.

1

У вас есть combineLatest оператор, который в основном делает то, что вы описываете. Он объединяет два наблюдаемых и дает вам последнее значение обоих потоков.

Итак:

--a - Ь ----- гр --- -x ----- ----- д р- -combineLatest- --a- -bb --- cc xxddp

Это должно позволить вам делать то, что вы хотите, если я правильно понимаю.

Вот официальная ссылка док: https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/combinelatest.md

+0

Комбинация последней приведет к тому, что в качестве подписки будут добавлены как «фильтрованные пользователи», так и «добавленные пользователи». Но я хочу, чтобы они были заполнены только тогда, когда срабатывает 'addedUsers $'. –

1

В конце концов я сделал это, добавив дополнительный предмет:

var filteredUsers$ = ... // users from filter 
var addedUsers$ = ... // users dragged on chart 
var usersToDraw$ = new Subject(); 

подписки:

usersToDraw$ 
    .subscribe(usersToDraw => { 
     redrawChart(usersToDraw); 
    }); 

filteredUsers$ 
    .subscribe(filteredUsers => { 
     usersToDraw$.next(filteredUsers); 
    }); 

Observable 
    .combineLatest(filteredUsers$, addedUsers$) 
    .filter(([filteredUsers, addedUsers]) => addedUsers != null) 
    .subscribe(([filteredUsers, addedUsers]) => { 
     // we 'clear' stream so the same users won't be added twice 
     addedUsers$.next(null); 

     usersToDraw$.next(/* combining users */); 
    }); 

UPDATE

Решение может быть улучшена с withLatestFrom (спасибо @nova)

usersToDraw$ 
    .subscribe(usersToDraw => { 
     redrawChart(usersToDraw); 
    }); 

filteredUsers$ 
    .subscribe(filteredUsers => { 
     usersToDraw$.next(filteredUsers); 
    }); 

addedUsers$ 
    .withLatestFrom(filteredUsers$) 
    .subscribe(([addedUsers, filteredUsers]) => { 
     usersToDraw$.next(/* combining users */); 
    });