如何解决用可观察的条件过滤观察到的阵列
我有一个请求,该请求返回一个对象数组。每个对象都包含一个ID,我可以通过该ID发送另一个请求。基于此结果,我想过滤数组。简化示例:
function getAllObjects(): Observable<{ id: number }[]> {
return of([
{ id: 1 },{ id: 2 },{ id: 3 },{ id: 4 },]);
}
function checkObject(obj): Observable<boolean> {
return of(obj.id % 2 === 0);
}
getAllObjects().pipe(
// TODO
).subscribe(console.log); // I only want to see objects here which passed the async check
解决方法
对您有用吗?
getAllObjects().pipe(
flatMap((ar) => ar),concatMap((obj) => combineLatest([of(obj),checkObject(obj)])),filter(([_,checkResult]) => checkResult),map(([obj]) => obj),toArray(),).subscribe(console.log);
编辑,我看到您已经找到了解决方案,我的要简单得多,并且我认为您需要一个对象流,而不是将它们作为数组返回。所以我在Edit中添加了toArray。
,可能不是最简单但也可以使用的解决方案
getAllObjects()
.pipe(
switchMap(array =>
combineLatest(array
.map(obj =>
checkObject(obj)
.pipe(
distinctUntilChanged(),map(boolean => boolean ? obj : null)
)
)
)
),map(array => array.filter(obj => obj))
)
.subscribe(console.log);
考虑到实时可能的变化
function getAllObjects(): Observable<{ id: number }[]> {
return timer(0,10000)
.pipe(
map(() => [
{ id: 1 },{ id: 2 },{ id: 3 },{ id: 4 },])
);
}
function checkObject(obj): Observable<boolean> {
return timer(1000,5000)
.pipe(
map(() => obj.id % 2 === 0)
);
}
,
const objects$ = getAllObjects().pipe(concatAll());
const objectValidations$ = objects$.pipe(concatMap(checkObject));
zip(objects$,objectValidations$).pipe(
filter(([,validated]) => validated),map(([obj,]) => obj),toArray()
).subscribe(console.log);
更新: 我们可以通过并行化“检查”来改善上述解决方案的性能:
getAllObjects().pipe(
concatAll(),mergeMap(obj =>
checkObject(obj).pipe(
map(isValid => isValid? obj : undefined),filter(Boolean),)
),toArray()
)
那更好,因为如果我们假设以下checkObject
的实现(增加了延迟):
function checkObject(obj) {
return of(obj.id % 2 === 0).pipe(delay(1000));
}
然后,对于n个对象,先前的解决方案将花费n秒,而更新后的解决方案则需要1秒
,import { map,filter } from 'rxjs/operators';
map(items => items.filter(item => item.id % 2 === 0)),filter(items => items && items.length > 0)
首先使用map函数并像平常一样过滤数组。 然后,要确保您不会得到null或空数组,请使用filter函数,如果地图为null或空,则该函数不会调用订阅。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。