通过observable过滤可观察量

时间:2016-07-23 20:45:53

标签: rxjs reactivex

让我们考虑以下简化情况:

  • 我们有Observable类型的Observable苹果< Apple>
  • 每个Apple对象都有一个方法isRotten(),它返回Observable类型的observable<布尔值>保证发出至少一个布尔值。

我想过滤苹果可观察物,以便腐烂的苹果不会通过过滤器。更确切地说,当且仅当A.isRotten()发出的第一个项目为假时,苹果A才会通过过滤器。实现此过滤器的最佳方法是什么?

经过一番思考后,我可以想出这个:

apples
    .concatMap(apple => 
        apple.isRotten()
            .first()
            .filter(bool => bool)
            .map(bool => apple))

用javascript编写。 (... => ...是一个函数)。这有效,但我认为这是相当漫长和难以理解的。有没有更好的方法来做这种事情?

3 个答案:

答案 0 :(得分:2)

你得到的很好,而且,我想不出更简洁的做法。如果无序苹果不是问题,我可能会使用flatMap而不是concatMap

如果可读性对您来说是一个问题,只需将实现移动到它的一个函数中(例如filterObservable接受一个带值的函数并返回IObservable<bool>

答案 1 :(得分:0)

实现这种目标的一种方法是,对不起,我没有将其适应于水果过滤:

const orders$: Observable<Order[]> = searchOrders(...);

const filteredOrders$ = orders$.pipe(switchMap((orders) => {

    // take all orders and determine visibility based on an observable
    const visibilityRules = orders.map(o => {

        return {                    
            order: o,
            visible$: o.isPaidFor$   // this is an observable on an Order object
        };
    });

    const filtered = visibilityRules.map(o => o.visible$.pipe(map(visible => visible ? o.order : undefined )));
    return (filtered.length == 0) ? of([]) : combineLatest(filtered).pipe(map(combined => combined.filter(x => x != undefined)));

}));

这将过滤“ paidFor”订单,并在每次订单已付款或未付款时发出一个新数组。

注意:如果isPaidFor$的可观察值在两次搜索之间无法更改,则整个练习是没有意义的,因为没有理由提供这样的“实时视图”。仅当可观察对象实际上可以在搜索结果之间改变时,这才有意义。

如果需要,可以将其扩展到更复杂的规则(例如添加过滤复选框),这就是为什么我创建了中间visibilityRules数组的原因-严格来说,这只是为了提高可读性。

答案 2 :(得分:-3)

您可以这样做:

var seq = Rx.Observable.from([1, 2, 3, 4, 5, 6])
    .filter(x => {
        let isRotten = true;
        Rx.Observable.just(x % 2 === 0)
            .first()
            .subscribe(val => isRotten = val);

        if (isRotten) {
            return x;
        }
    });

seq.subscribe(x => console.log(x));