7

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

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

我想过滤可观察到的苹果,使烂苹果不通过过滤器。更准确地说,当且仅当 A.isRotten() 发出的第一项为 false 时,苹果 A 通过过滤器。实现此过滤器的最佳方法是什么?

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

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

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

4

3 回答 3

3

你所拥有的很好,而且,tbh,我想不出更简洁的方法。我可能会使用flatMap而不是concatMap如果乱序的苹果不是问题。

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

于 2016-07-24T04:22:56.640 回答
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$observable 在搜索之间不能改变,那么整个练习是没有意义的,因为没有理由提供这样的“实时视图”。仅当可观察对象实际上可以在搜索结果之间发生变化时,这才有意义。

如果需要,这可以扩展到更复杂的规则(例如添加过滤复选框)——这就是我创建中间visibilityRules数组的原因——严格来说,这只是为了便于阅读。

于 2019-11-06T05:53:33.890 回答
-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));
于 2016-07-23T23:31:09.783 回答