Я новичок в 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 подписке, очевидно, это решение не работает, и я не могу заставить что-то еще работать.
Любая помощь будет оценена, спасибо!





Кажется, у тебя слишком много внутренних 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, ну, с практической точки зрения - я очень рекомендую детская площадка, который я создал. С теоретической точки зрения - я чувствую вашу боль, текущей документации в основном не хватает простоты и прозрачности. Попробуйте Learnrxjs.io — у них есть хорошие примеры, и есть этот старая книга по RxJS 4, из которого вы могли бы почерпнуть некоторые концепции. + на RxJS есть пара яйцеголовых курсов, правда они за платным доступом.
@TanguyB, я только что погуглил некоторые ресурсы rxjs - и на самом деле есть масса руководств и статей на эту тему. Хотя, поскольку большинство из них я вижу впервые - я не могу честно рекомендовать их. Тем не менее, вот два видео, которые могут вам помочь: Быстрый старт RxJS с практическими примерами и серия видеоуроков от основных участников RxJS Бена Леша и Трейси Ли. В общем, просто погуглите, вы найдете то, что подходит вам лучше всего! ;)
@Привет, я попробовал ваше решение, оно не попало в часть подписки, какие-нибудь подсказки?
@TanguyB, я опаздываю :) +1 за store.select().take(1) от SnorreDan!
Эта версия немного более подробная, но, возможно, ее будет проще понять, поскольку она разделена на несколько частей. Хотя не проверял.
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]) => {});
Я попробовал ваше решение, похоже, оно не попало в часть подписки, есть какие-то подсказки?
Таким образом, forkJoin предполагает, что все Observables завершаются, но, вероятно, это не так в случае с store.select. Я изменил последний forkJoin на CombineLatest, это может решить проблему.
В качестве альтернативы мы могли бы сделать store.select полным, изменив его на «this.store.select(RegionState.region(group.regionId)).pipe(take(1))».
Я изменил все forkJoins в примере на combLatest сейчас, тогда это должно работать. Но если вы хотите получить только одно значение, вам следует вернуться к forkJoin и добавить «.pipe(take(1))» после всех наблюдаемых, которые не завершаются.
да, проблема действительно заключалась в store.select (если я делаю снимок selectsnapshot в магазине при подписке, он работает). Я попробую с вашим последним решением
Я попробую позже вечером и отвечу, если это сработает, хотя спасибо, я очень новичок в rxjs, так что это много :)