angular - RxJS 6 过滤和映射可观察的项目数组
问题描述
在我使用 RxJS 6.3.3 的 Angular 7.1.1 应用程序中,应将可观察的计划数组转换为可观察的活动计划卡数组。有源滤波器是:
filter(plan => plan.is_active)
计划到卡片的转化为:
map(plan => new PlanCard(plan, 1, 1))
所以,据推测,答案是这样的:
plans: Observable<Plan[]> = getPlans();
cards: Observable<PlanCard[]> = plans.pipe(
mergeAll(),
filter(plan => plan.is_active),
map(plan => new PlanCard(plan, 1, 1)),
toArray()
);
但很可惜,cards
是空的。
计划可以通过以下方式正确转换为卡片:
cards: Observable<PlanCard[]> = plans.pipe(
map(plans => plans.map(plan => new PlanCard(plan, 1, 1)))
);
但不幸的是,添加过滤器不会过滤计划:
cards: Observable<PlanCard[]> = plans.pipe(
filter(plans => plans.filter(plan => plan.is_active)),
map(plans => plans.map(plan => new PlanCard(plan, 1, 1)))
);
有更好的想法吗?
export const planData: Plan[] = [{
name: 'P1',
is_active: true
}, {
name: 'P2',
is_active: true
}, {
name: 'P3',
is_active: true
}, {
name: 'P4',
is_active: true
}, {
name: 'P5',
is_active: false
}];
export const plans = createObservable(planData);
解决方案
mergeAll 合并一个 observable 的 observable。
你要
cards: Observable<PlanCard[]> = plans.pipe(
map(plans => plans.filter(plan => plan.is_active)), // An array comes down the pipe, you don't want to filter out the arrays but the elements in the array
map(plans => plans.map(plan => new PlanCard(plan, 1, 1))), // An array of active plans can be mapped into an array of PlanCards
reduce((results, plans) => [...results, ...plans], []) // Reduce all the arrays into a single array
);
如果您希望每次新阵列下降时减少的累加器从管道下降,您可以使用扫描而不是减少,只有在所有阵列都下降到管道后才会触发。
我通常不使用过滤器后跟地图,但更容易看到发生了什么,我通常会在一个步骤中使用减少,
plans => plans.reduce((results, plan) => plan.is_active ? [...results, new PlanCard(plan, 1, 1)] : results, [])
与过滤器后跟映射相同,但在一次迭代中而不是两次迭代中完成。
当您拥有数组的可观察对象时,这可能会非常令人困惑,您需要考虑要将哪些函数应用于可观察对象以及要将哪些函数应用于管道中的数组。
const { from } = rxjs;
const { map, reduce } = rxjs.operators;
const plans = from([
[{id: 1, is_active: true}, {id: 2, is_active: false}, {id: 3, is_active: true}, {id: 4, is_active: true}],
[{id: 5, is_active: true}, {id: 6, is_active: true}],
[{id: 7, is_active: false}, {id: 8, is_active: true}, {id: 9, is_active: true}],
[{id: 10, is_active: true}, {id: 11, is_active: false}, {id: 12, is_active: true}, {id: 13, is_active: false}],
]);
function PlanCard(plan) {
this.id = plan.id;
}
plans.pipe(
map(plans => plans.reduce((results, plan) => plan.is_active ? [...results, new PlanCard(plan, 1, 1)] : results, [])),
reduce((results, plans) => [...results, ...plans], [])
).subscribe(results => { console.log(results); });
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.3.3/rxjs.umd.min.js"></script>
推荐阅读
- spring - 无法使用 spring 对同义词进行更改
- python - 无法安装pysiddhi
- django - django - 将用户配置文件添加到注册表单。表格未提交
- ios - AVPlayer 中断通知不起作用
- database - 如何找出 Postgres 数据库中的哪些列不能为空?
- ios - 如何使用 Swift 使用日期格式化程序设置默认时间?
- javascript - UiKit Grid、Margin 和 Cover 在 html 上不起作用是通过 ajax 加载的
- xamarin.forms - 无法在希腊语的 sqlite-net 查询中处理字符串
- python - 芹菜任务在 Django 应用程序中执行多次
- stackdriver - stackdriver:自定义与基于日志的指标