Как сделать так, чтобы у моего наблюдаемого были значения для использования в эффекте NGRX? - PullRequest
0 голосов
/ 03 апреля 2020

Если честно, я абсолютный новичок в NGRX и только ограниченный опыт в rx js. Но по сути у меня есть код, подобный следующему:

@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. Кажется, все выглядит хорошо, но когда я пытаюсь на самом деле пересмотреть коллекции для результата наблюдаемых из сервиса, они еще не реализованы. Я готов попробовать что угодно, но в простейшей форме проблема заключается в следующем:

Две наблюдаемые должны быть вызваны либо в сходном порядке, либо довольно близко. Их «результаты» имеют тип номера []. Сложная коллекция классов, которая имеет свойство 'id', которое должно включать это число []. Это прекрасно работает, когда все результаты не являются асинхронными c или в компоненте. (Я проверяю значения c с переменными, чтобы проверить мой «фильтр», затем »включает« logi c, и это работает) Но в NGRX Я в некотором роде растерялся, так как ему нужен метод возврата, и я просто недостаточно хорош в rx js, чтобы сформулировать способ сделать его счастливым и обеспечить, чтобы наблюдаемые объекты были полностью реализованы, чтобы их значения из служб использовались надлежащим образом. Снова я вижу, что мой консольный журнал «фильтров» там. Тем не менее, когда я делаю «длину», она всегда равна нулю, поэтому я знаю, что где-то есть проблема синхронизации. Буду признателен за любую оказанную помощь.

1 Ответ

1 голос
/ 03 апреля 2020

Если я понимаю проблему, вы можете попытаться заменить это

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. Таким образом, вы находитесь в ситуации, когда вышестоящая Наблюдательная система уведомляет что-то, что принимается оператором, который создает новую Наблюдаемую . Аналогичные ситуации, когда необходимо использовать такие операторы, как switchMap, mergeMap (он же flatMap), concatMap и exhastMap. Такие операторы сглаживают внутреннюю наблюдаемую и возвращают ее результат. Это причина, почему я бы использовал один из этих операторов сплющивания. Почему 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

...