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

ggr*_*nig 5 rxjs

假设我有一个可观察的项目

let items$ = Observable<Item[]>
Run Code Online (Sandbox Code Playgroud)

每个 Item 都有一个 property isSelected$,它本身就是一个 Observable:

private isSelected$: Observable<boolean>
Run Code Online (Sandbox Code Playgroud)

接收当前选定的所有项目的列表的最佳方式是什么?我的解决方案看起来不太正确:

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))
        )))
Run Code Online (Sandbox Code Playgroud)

它很有效,我以前也用过它,但对于我必须经常做的事情来说,它的结构非常复杂。一定会有更好的办法。

注意:订阅者需要所有选定项目的列表,而不是单个项目的流。

示例: items$将发出以下列表:

[{id: 1, isSelected$: of(true)}, 
    {id: 2, isSelected$: of(false)}, 
    {id:3, isSelected$: of(true)}]
Run Code Online (Sandbox Code Playgroud)

作为我们订阅的结果,我们希望获得列表:

[{id: 1}, {id: 3}]
Run Code Online (Sandbox Code Playgroud)

Pic*_*cci 6

你可能想尝试这样的事情

.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()
        )
    ),
)
Run Code Online (Sandbox Code Playgroud)

首先,我们获取 的通知items$,它是一个数组,并将其转换为一次发出一项的 Observable。

关键在于作为参数传递给 的函数mergeMap

item.isSelected返回Observable<boolean>用于过滤的 。对于这样的 Observable,我们应用一个转换 viamap将其转换为一个拥有 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)},
    ]
);
Run Code Online (Sandbox Code Playgroud)