【问题标题】:Return an Observable by mapping another Observable通过映射另一个 Observable 返回一个 Observable
【发布时间】:2018-11-21 09:37:52
【问题描述】:

我正在尝试映射一个 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();
  }

问题是打字稿表明我的 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 取回了一些数据,但它发出了多个 observables 而不是组合流:

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;
    });

【问题讨论】:

  • 试试return this.getJobsbyGroup(group.id);
  • 大概想用flatMap
  • 差不多了,谢谢-我注意到mergeMap正在返回一个数组-我将发布更新
  • @rhysclay - 没问题,修复它
  • 对不起,但现在我得到 'concatMap' 在 Observable 类型上不存在

标签: angular rxjs


【解决方案1】:

以下方法详细讨论: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));
    }

【讨论】:

    【解决方案2】:

    好的,首先您在getJobsByUser 函数中缺少两个return 语句(如下所示,大写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[]user 的所有groups 中的所有jobs

    您可以使用多个运算符来展平结果,例如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();
    }
    

    每一行都是这样说的:

    1. 给我一个groupsuser //返回Observable&lt;Group[]&gt;
    2. 展平Group[]的结果 //返回Observable&lt;Group&gt;
    3. 给我一个jobsgroup // 返回Observable&lt;Job[]&gt;
    4. 展平job[]的结果 //返回Observable&lt;Job&gt;
    5. Job 的所有事件收集到一个具有Job[] 的事件中

    【讨论】:

    • 快到了 - 打字稿告诉我这将返回 Observable[]> 。我觉得需要 switchMap 但我就是不知道怎么做
    • @rhysclay 你是对的,我更新了我的答案,包括一步一步的解释。
    猜你喜欢
    • 1970-01-01
    • 2021-12-28
    • 2020-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-05
    • 2019-01-23
    • 1970-01-01
    相关资源
    最近更新 更多