通过一个可观察对象过滤另一个可观察对象

8

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

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

我想要过滤掉腐烂的苹果。更准确地说,只有当A.isRotten()发出的第一个布尔值为false时,才认为苹果A通过了筛选。最佳实现方法是什么?

经过一些思考,我想到了以下解决方案:

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

这段代码是用JavaScript编写的(... => ... 是一个函数)。虽然它能够运行,但我认为这样写有些冗长且难以理解。是否有更好的方法来处理这种情况呢?

3个回答

4
你的代码很好,实话说,我想不到更简洁的方法了。如果顺序不重要,我可能会使用flatMap而不是concatMap
如果可读性是问题,只需将实现移入它的一个函数中(例如filterObservable,该函数接受一个函数,该函数接受一个值并返回IObservable<bool>)。

谢谢你的回答,我希望有类似于filterObservable的东西存在。但我想我必须自己实现它。 - Ward Beullens

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数组的原因-严格来说,这只是为了可读性。


-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));

你确定吗?我认为这不起作用,因为x.isRotten()不返回布尔值,它返回一个发出布尔值的Observable。 - Ward Beullens
我创建了下面的fiddle,它验证了过滤器运算符不能与Observables一起使用。http://jsfiddle.net/pgcrwauj/ - Ward Beullens
@WardBeullens 请查看更新后的代码。一开始我没有理解你的问题。 - Toan Nguyen
很抱歉,但我认为你的方法并不好。它只能工作(说实话,我很惊讶它能工作),因为Observable.just非常快地解析。如果你添加一个延迟(就像方法必须执行http调用之类的操作),它将不再起作用。http://jsfiddle.net/8qu2c29j/ - Ward Beullens
如果代码需要额外的工作来获取内部Observable,那么我会以不同的方式处理。具体而言,我会查看map以获取即时值+原始值,然后过滤map的输出。 - Toan Nguyen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接