RXJS — несколько наблюдаемых вызовов массива свойств

Я новичок в rxjs, и у меня довольно простой случай, который я не могу решить в angular.

У меня есть http-вызов для получения группы, эта группа содержит список «идентификаторов друзей», список «идентификаторов жанров» и «идентификатор региона».

Чтобы получить объекты приятеля через «идентификаторы приятеля», я должен сделать вызов API через мою службу (которая возвращает 1 приятеля с заданным идентификатором).

Чтобы получить свои жанровые объекты, я могу получить их из своего магазина, то же самое для региона.

Проблема в том, что я не могу найти решение с трубами.

this.buddyService.getGroup(groupId).pipe(
    mergeMap((group) => forkJoin(
          mergeMap(() => forkJoin(group.buddyIds.map((id) => this.buddyService.getBuddy(id)))), 
          mergeMap(() => forkJoin(group.genreIds.map((id) => this.store.select(GenreState.genre(id))))),
          switchMap(() => this.store.select(RegionState.region(group.regionId))))
    ), takeUntil(this.destroyed$)
).subscribe(([group, buddies, genres, region]) => {

});

Таким образом, первая карта слияния будет заключаться в том, чтобы собрать все результаты вместе в 1 подписке, затем у меня есть 3 дополнительных вызова, чтобы получить друзей, жанры и регион.

Я хотел бы получить свой первоначальный ответ (группу) и результаты 3 дополнительных вызовов в 1 подписке, очевидно, это решение не работает, и я не могу заставить что-то еще работать.

Любая помощь будет оценена, спасибо!

Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
7
0
4 932
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Кажется, у тебя слишком много внутренних mergeMap. Попробуй это

this.buddyService.getGroup(groupId).pipe(
  mergeMap((group) => forkJoin(
    of(group),
    forkJoin(...group.buddyIds.map((id) => this.buddyService.getBuddy(id))), 
    forkJoin(...group.genreIds.map((id) => this.store.select(GenreState.genre(id)))),
    this.store.select(RegionState.region(group.regionId)))
  ),
  takeUntil(this.destroyed$)
)
.subscribe(([group, buddies, genres, region]) => {});

Основная проблема заключалась в том, что вы объединили методы «построения», которые Создайте Observables (например, forkJoin), с операторами, которые работать на существующих Observables (например, switchMap или mergeMap).

Проверьте разницу сами: switchMap против forkJoin

Я написал это без глубокого тестирования, так что это может не сработать сразу :)

Я попробую позже вечером и отвечу, если это сработает, хотя спасибо, я очень новичок в rxjs, так что это много :)

TanguyB 22.03.2019 22:00

есть ли у вас какие-либо ресурсы помимо официальных документов для rxjs, я не нахожу их такими ясными

TanguyB 22.03.2019 22:07

@TanguyB, ну, с практической точки зрения - я очень рекомендую детская площадка, который я создал. С теоретической точки зрения - я чувствую вашу боль, текущей документации в основном не хватает простоты и прозрачности. Попробуйте Learnrxjs.io — у них есть хорошие примеры, и есть этот старая книга по RxJS 4, из которого вы могли бы почерпнуть некоторые концепции. + на RxJS есть пара яйцеголовых курсов, правда они за платным доступом.

kos 22.03.2019 22:24

@TanguyB, я только что погуглил некоторые ресурсы rxjs - и на самом деле есть масса руководств и статей на эту тему. Хотя, поскольку большинство из них я вижу впервые - я не могу честно рекомендовать их. Тем не менее, вот два видео, которые могут вам помочь: Быстрый старт RxJS с практическими примерами и серия видеоуроков от основных участников RxJS Бена Леша и Трейси Ли. В общем, просто погуглите, вы найдете то, что подходит вам лучше всего! ;)

kos 22.03.2019 23:07

@Привет, я попробовал ваше решение, оно не попало в часть подписки, какие-нибудь подсказки?

TanguyB 23.03.2019 00:18

@TanguyB, я опаздываю :) +1 за store.select().take(1) от SnorreDan!

kos 23.03.2019 00:58
Ответ принят как подходящий

Эта версия немного более подробная, но, возможно, ее будет проще понять, поскольку она разделена на несколько частей. Хотя не проверял.

import {combineLatest} from 'rxjs';

...

  const group$ = this.buddyService.getGroup(groupId);
  const buddies$ = group$.pipe(mergeMap(group => combineLatest(group.buddyIds.map((id) => this.buddyService.getBuddy(id))));
  const genres$ = group$.pipe(mergeMap(group => combineLatest(group.genreIds.map((id) => this.store.select(GenreState.genre(id))));
  const region$ = group$.pipe(switchMap(group => this.store.select(RegionState.region(group.regionId)))));

  combineLatest([group$, buddies$, genres$, region$])
    .pipe(takeUntil(this.destroyed$))
    .subscribe(([group, buddies, genres, region]) => {});

Я попробовал ваше решение, похоже, оно не попало в часть подписки, есть какие-то подсказки?

TanguyB 23.03.2019 00:19

Таким образом, forkJoin предполагает, что все Observables завершаются, но, вероятно, это не так в случае с store.select. Я изменил последний forkJoin на CombineLatest, это может решить проблему.

SnorreDan 23.03.2019 00:37

В качестве альтернативы мы могли бы сделать store.select полным, изменив его на «this.store.select(RegionState.region(group.regionId)).pipe(‌​take(1))».

SnorreDan 23.03.2019 00:46

Я изменил все forkJoins в примере на combLatest сейчас, тогда это должно работать. Но если вы хотите получить только одно значение, вам следует вернуться к forkJoin и добавить «.pipe(take(1))» после всех наблюдаемых, которые не завершаются.

SnorreDan 23.03.2019 00:51

да, проблема действительно заключалась в store.select (если я делаю снимок selectsnapshot в магазине при подписке, он работает). Я попробую с вашим последним решением

TanguyB 23.03.2019 00:55

Другие вопросы по теме