rxjs - 如何让我的 observable 具有用于 NGRX 效果的值
问题描述
老实说,我是 NGRX 的菜鸟,在 rxjs 方面的经验有限。但基本上我有类似这样的代码:
@Effect()
applyFilters = this.actions$.pipe(
ofType<ApplyFilters>(MarketplaceActions.ApplyFilters),
withLatestFrom(this.marketplaceStore.select(appliedFilters),
this.marketplaceStore.select(catalogCourses)),
withLatestFrom(([action, filters, courses]) => {
return [courses,
this.combineFilters([
this.getCourseIdsFromFiltersByFilterType(filters, CatalogFilterType.TRAINING_TYPE),
this.getCourseIdsFromFiltersByFilterType(filters, CatalogFilterType.INDUSTRIES)
])
];
}),
map(([courses, filters]) => {
console.log('[applyFilters effect] currently applied filters =>', filters);
console.log('courseFilters', filters);
const filteredCourses = (courses as ShareableCourse[]).filter(x => (filters as number[]).includes(+x.id));
console.log('all', courses);
console.log('filtered', filteredCourses);
return new SetCatalogCourses(filteredCourses);
})
);
辅助方法:
private combineFilters(observables: Observable<number[]>[]): number[] {
if (!observables.some(x => x)) {
return [];
} else {
let collection$ = (observables[0]);
const result: number[] = [];
for (let i = 0; i < observables.length; i++) {
if (i >= 1) {
collection$ = concat(collection$, observables[i]) as Observable<number[]>;
}
}
collection$.subscribe((x: number[]) => x.forEach(y => result.push(y)));
return result;
}
}
所以基本上存储对象被填充,我可以得到它们。我知道“this.getCourseIdsFromFiltersByFilterType(args)”的可观察值确实与它们所在的“过滤器”的控制台日志一样工作。但手术时机不对。我一直在阅读,在尝试了 SwitchMap、MergeMap、Fork 之后就迷路了。一切看起来都还不错,但是当我尝试实际遍历集合以获取服务中可观察的结果时,它们还没有实现。我愿意尝试任何事情,但最简单的问题是:
需要以相似的顺序或非常接近的顺序调用两个可观察对象。他们的“结果”是 number[] 类型。具有此 number[] 应该能够包含的 'id' 属性的复杂类集合。当所有结果都不是异步的或在一个组件中时,这工作得很好。(我用变量来模拟静态值以检查我的“过滤器”然后“包含”逻辑并且它有效)但是在 NGRX 我有点迷失了它需要一个返回方法,我根本不够擅长 rxjs 来制定一种让它快乐的方法,并确保充分实现可观察对象的价值,使其从服务中得到适当使用。我再次可以看到我的“过滤器”控制台日志在那里。然而,当我做一个“长度”时,它总是为零,所以我知道某个地方存在时间问题。
解决方案
如果我理解这个问题,您可能想尝试替换它
withLatestFrom(([action, filters, courses]) => {
return [courses,
this.combineFilters([
this.getCourseIdsFromFiltersByFilterType(filters, CatalogFilterType.TRAINING_TYPE),
this.getCourseIdsFromFiltersByFilterType(filters, CatalogFilterType.INDUSTRIES)
])
];
}),
像这样的东西
switchMap(([action, filters, courses]) => {
return forkJoin(
this.getCourseIdsFromFiltersByFilterType(filters, CatalogFilterType.TRAINING_TYPE),
this.getCourseIdsFromFiltersByFilterType(filters, CatalogFilterType.INDUSTRIES
).pipe(
map(([trainingFilters, industryFilters]) => {
return [courses, [...trainingFilters, ...industryFilters]]
})
}),
现在做一些解释。
当你退出这个
withLatestFrom(this.marketplaceStore.select(appliedFilters),
this.marketplaceStore.select(catalogCourses)),
您将此数组传递给下一个运算符[action, filters, courses]
。
下一个操作员必须调用一些远程 API,因此必须创建一个新的 Observable。因此,当上游 Observable 通知由操作员获取的创建新 Observable的某些内容时,您会遇到这种情况。类似的情况是必须使用诸如switchMap
, mergeMap
(aka flatMap
), concatMap
and之类的运算符。exhastMap
此类运算符将内部 Observable展平并返回其结果。这就是为什么我会使用这些展平运算符之一的原因。为什么switchMap
在你的情况下?这不是一个真正的短篇小说。或许阅读这篇文章可以带来一些启发。
现在让我们看看传递给的函数switchMap
return forkJoin(
this.getCourseIdsFromFiltersByFilterType(filters, CatalogFilterType.TRAINING_TYPE),
this.getCourseIdsFromFiltersByFilterType(filters, CatalogFilterType.INDUSTRIES
).pipe(
map(([trainingFilters, industryFilters]) => {
return [courses, [...trainingFilters, ...industryFilters]]
})
此函数首先通过 并行执行 2 个远程 API 调用forkJoin
,然后获取这 2 个调用的结果并将其映射到一个新数组,其中包含和courses
的连接trainingFilters
industryFilters
推荐阅读
- php - 在 Symfony WebTestCase (PHPUnit) 的单个类中设置测试执行顺序
- javascript - React 中的高阶组件 (HOC) 导致包装组件的额外渲染
- c# - 在 foreach 循环中创建的同一线程正在执行多次
- javascript - 从下拉列表中触发 Ajax 时,先前的行元素正在更改
- ruby-on-rails - 检查网站是否使用 wordpress 构建或不在 rails 中
- r - 基于有错误的索引列创建新列
- javascript - 为什么我的 lambda 函数给我消息内部服务器错误而不是正确的错误响应?
- javascript - 如何在 ReactJS 文件中正确导入函数
- javascript - 启用 Express、GraphQL 和 CORS 的 NodeJS CSRF 保护
- android - 'com.android.support:appcompat-v7:27.1.1' 显示错误