我正在尝试映射一个observable,从我返回的observable中获取一个值,然后将该值提供给另一个observable并返回该结果。以下是我到目前为止的情况:
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();
}
问题是typescript表明我的getJobsByUser函数将返回一个observable类型:void。当我在我的模板上输出它时,我什么都没有或未定义。我觉得我需要使用switchMap但是我对rx / js有点模糊。我不确定如何返回Job []
类型的Observable更新:在@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:我设法从firestore获取了一些数据,但是它发出了多个可观察数据而不是组合流:
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;
});
答案 0 :(得分:4)
以下方法详细讨论了:Way to handle Parallel Multiple Requests
以下方法使用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));
}
答案 1 :(得分:1)
好的,首先您在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
的{{1}} //返回user
Observable<Group[]>
//的结果//返回Group[]
Observable<Group>
的{{1}} //返回jobs
group
//的结果//返回Observable<Job[]>
job[]
的所有事件收集到一个具有Observable<Job>