Как отфильтровать наблюдаемые значения на основе наблюдаемого свойства каждого значения - PullRequest
0 голосов
/ 03 сентября 2018

Предположим, у меня есть наблюдаемые предметы

let items$ = Observable<Item[]>

и каждый предмет имеет свойство isSelected$, которое само по себе является наблюдаемым:

private isSelected$: Observable<boolean>

Как лучше всего получить список всех предметов, которые в данный момент выбраны? Мое решение выглядит не совсем правильно:

items$.pipe(
    switchMap(items =>
        combineLatest(items.map(item =>
                item.isSelected$.pipe(
                    map(isSelected => ({item: item, isSelected: isSelected})))),
            map(items => items.filter(item => item.isSelected).map(item => item.item))
        )))

Это работает, и я использовал его раньше, но это такая сложная конструкция для чего-то, что мне приходится делать довольно часто. Должен быть лучший способ.

Примечание: Подписчику нужен список всех выбранных элементов, а не поток отдельных элементов.

Пример: items$ выдаст следующий список:

[{id: 1, isSelected$: of(true)}, 
    {id: 2, isSelected$: of(false)}, 
    {id:3, isSelected$: of(true)}]

И в результате нашей подписки мы хотели бы получить список:

[{id: 1}, {id: 3}]

1 Ответ

0 голосов
/ 04 сентября 2018

Вы можете попробовать что-то вроде этого

.pipe(
    switchMap(
        items => from(items).pipe(
            mergeMap(item => item.isSelected$.pipe(map(sel => ({sel, item})))),
            filter(data => data.sel),
            map(data => ({id: data.item.id})),
            toArray()
        )
    ),
)

Сначала мы берем уведомление о items$, которое является массивом, и преобразуем его в наблюдаемый объект, который испускает один элемент за раз.

Ключ в функции передается в качестве параметра mergeMap.

item.isSelected возвращает Observable<boolean>, который будет использоваться для фильтрации. К такой наблюдаемой мы применяем преобразование через map, чтобы превратить его в объект, который имеет 2 свойства: критерии выбора и весь элемент.

Остальное - просто фильтрация на основе критериев выбора, а затем преобразование снова, чтобы получить item.

Я протестировал приведенный выше код со следующими данными теста

const items$ = of(
    [
        {id: 1, isSelected$: of(true)},
        {id: 2, isSelected$: of(false)},
        {id: 3, isSelected$: of(true)},
        {id: 4, isSelected$: of(true)},
    ],
    [
        {id: 10, isSelected$: of(true)},
        {id: 20, isSelected$: of(true)},
        {id: 30, isSelected$: of(false)},
        {id: 40, isSelected$: of(false)},
    ]
);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...