Возврат наблюдаемой путем сопоставления другой наблюдаемой
Я пытаюсь отобразить наблюдаемую информацию, получить значение из возвращенной наблюдаемой, затем передать это значение в другую наблюдаемую и вернуть этот результат. Вот что у меня так далеко:
getJobsByUser(user: User): Observable<Job[]> {
return this.getUsersGroupsAsObservable(user.uid, 'contacts').map(groups => {
groups.map(group => {
this.getJobsbyGroup(group.id);
});
});
getJobsbyGroup(groupId: string): Observable<Job[]> {
return this.afs
.collection<Job>('jobs', ref => ref.where(`group.${groupId}`, '==', true))
.valueChanges();
}
getUsersGroupsAsObservable(
userId: string,
type: string = 'users',
): Observable<Group[]> {
return this.afs
.collection<Group>('groups', ref =>
ref.where(`${type}.${userId}`, '==', true),
)
.valueChanges();
}
Проблема заключается в том, что машинопись показывает, что моя функция getJobsByUser будет возвращать наблюдаемую информацию типа:void. Когда я вывожу его на свой шаблон, я ничего не получаю или не определяю. Я чувствую, что мне нужно использовать switchMap, но я немного размыт с rx/js. Я не уверен, как вернуть Observable типа Job[]
Обновление: с помощью @Pranay Rana я сейчас возвращаю массив и могу получить первое значение, например так:
getJobsByUser(user: User): Observable<Job[]> {
return this.getUsersGroupsAsObservable(user.uid, 'contacts').pipe(
mergeMap(groups => {
// returns an array of groups - we need to map this
return this.getJobsbyGroup(groups[0].id); // works with the first value - do we need another map here?
}),
);
}
Обновление 2: мне удалось получить некоторые данные из хранилища, но он испускает несколько наблюдаемых, а не объединенный поток:
this.fb.getUsersGroupsAsObservable(user.uid, 'contacts')
.switchMap(groups => {
return groups.map(group => this.fb.getJobsbyGroup(group.id));
})
.subscribe(res => {
console.log(res);
// this emits multiple observables rather than one
this.job$ = res;
});
2 ответа
Ниже подробно обсуждается подход: Способ обработки параллельных множественных запросов
Ниже подход использовать mergemap
getJobsByUser(user: User) {
return this.getUsersGroupsAsObservable(user.uid, 'contacts').pipe(
mergeMap(group => this.getJobsbyGroup( group.id))
);
}
callingfunction(){
const requests = this.getJobsByUser(this.user);
requests.subscribe(
data => console.log(data), //process item or push it to array
err => console.log(err));
}
Вы также можете использовать forkJoin
getJobsByUser(user: User) {
return this.getUsersGroupsAsObservable(user.uid, 'contacts').pipe(
map(group => this.getJobsbyGroup( group.id))
);
}
callingfunction(){
const requests = forkJoin(this.getJobsByUser(this.user));
requests.subscribe(
data => console.log(data), //process item or push it to array
err => console.log(err));
}
Итак, сначала вам не хватает двух return
заявления в getJobsByUser
функция (показанная ниже с большой буквы RETURN
:
getJobsByUser(user: User): Observable<Job[]> {
return this.getUsersGroupsAsObservable(user.uid, 'contacts').map(groups => {
RETURN groups.map(group => {
RETURN this.getJobsbyGroup(group.id);
});
});
Или, немного более элегантно:
getJobsByUser(user: User): Observable<Job[]> {
return this.getUsersGroupsAsObservable(user.uid, 'contacts')
.map(groups => groups.map(group => this.getJobsbyGroup(group.id)));
}
Теперь нам нужно сгладить результат, потому что, если я правильно понял, 1 user
имеет много groups
и каждый group
много jobs
и вы хотите, чтобы ваш конечный результат был просто Job[]
со всеми jobs
из всех groups
из user
,
Вы можете использовать несколько операторов, чтобы сгладить результаты, например, switchMap
, или же concatMap
, Вот пример:
getJobsByUser(user: User): Observable<Job[]> {
return this.getUsersGroupsAsObservable(user.uid, 'contacts')
.concatMap(groups => groups)
.concatMap(group => this.getJobsbyGroup(group.id))
.concatMap(jobs => jobs)
.toArray();
}
Каждая строка говорит следующее:
- Достань мне
groups
дляuser
// возвращаетObservable<Group[]>
- Свести результат
Group[]
// возвращаетObservable<Group>
- Достань мне
jobs
дляgroup
// возвращаетObservable<Job[]>
- Свести результат
job[]
// возвращаетObservable<Job>
- Соберите все события
Job
на одно событие, которое имеетJob[]