让我们考虑以下简化情况:
我想过滤苹果可观察物,以便腐烂的苹果不会通过过滤器。更确切地说,当且仅当A.isRotten()发出的第一个项目为假时,苹果A才会通过过滤器。实现此过滤器的最佳方法是什么?
经过一番思考后,我可以想出这个:
apples
.concatMap(apple =>
apple.isRotten()
.first()
.filter(bool => bool)
.map(bool => apple))
用javascript编写。 (... => ...是一个函数)。这有效,但我认为这是相当漫长和难以理解的。有没有更好的方法来做这种事情?
答案 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));