如何根据每个值的可观察属性过滤出可观察值

时间:2018-09-03 20:48:23

标签: rxjs

假设我有一个可观察的物品

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 :(得分:3)

您可能想尝试类似的东西

.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$(它是一个数组)的通知,并将其转换为一个Observable,它在此时发出一个项目。

然后键在函数中作为参数传递给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)},
    ]
);