1

老实说,我是 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 来制定一种让它快乐的方法,并确保充分实现可观察对象的价值,使其从服务中得到适当使用。我再次可以看到我的“过滤器”控制台日志在那里。然而,当我做一个“长度”时,它总是为零,所以我知道某个地方存在时间问题。

4

1 回答 1

1

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

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), concatMapand之类的运算符。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的连接trainingFiltersindustryFilters

于 2020-04-03T15:30:32.983 回答