如何让我的可观察对象具有在 NGRX 效果中使用的值

How do I get my observable to have it's values for use in an NGRX effect

老实说,我是 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)' 的可观察对象确实像在 'filters' 的控制台日志上一样工作。但是操作的时机是错误的。我一直在阅读,但在尝试 SwitchMap、MergeMap、Fork 后迷路了。一切看起来都还不错,但是当我尝试实际遍历集合以获取来自服务的可观察结果时,它们尚未实现。我愿意尝试任何事情,但最简单的问题是:

需要以相似或非常接近的顺序调用两个可观察对象。他们的 'results' 是 number[] 类型。一个复杂的 class 集合,其中 属性 个 'id' 应该能够包含此数字[]。当所有结果不是异步的或在组件中时,这工作得很好。(我用变量事件虚拟静态值来检查我的 'filter' 然后 'includes' 逻辑并且它有效)但是在 NGRX 我有点迷失了,因为它需要一个 return 方法,而我在 rxjs 方面还不够好,无法制定一种方法来让它快乐,并确保充分实现 observables 的价值,以便适当地使用服务。我再次看到 'filters' 的控制台日志在那里。然而,当我对其执行 'length' 时,它始终为零,因此我知道某处存在计时问题。任何帮助深表感谢。

如果我理解这个问题,你可能想尝试替换这个

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]

下一个运算符必须调用一些远程 APIs,因此必须创建一个新的 Observable。所以你处于这样一种情况,上游 Observable 通知了一些被创建 new Observable 的操作员获取的东西。类似的情况是必须使用 switchMapmergeMap(又名 flatMap)、concatMapexhastMap 等运算符。这样的操作符 flatten 内部 Observable 和 return 它的结果。这就是为什么我会使用这些展平运算符之一的原因。为什么 switchMap 在你的情况下?这不是一个短篇小说。也许reading this可以投射一些光

现在让我们看看传递给switchMap

的函数
return forkJoin(
         this.getCourseIdsFromFiltersByFilterType(filters, CatalogFilterType.TRAINING_TYPE),
         this.getCourseIdsFromFiltersByFilterType(filters, CatalogFilterType.INDUSTRIES
      ).pipe(
         map(([trainingFilters, industryFilters]) => {
            return [courses, [...trainingFilters, ...industryFilters]]
         })

该函数首先通过forkJoin并行执行2个远程API调用,然后获取这2个调用的结果并将其映射到包含coursestrainingFiltersindustryFilters

的串联