使用rxjs Observable <Array <T>,如何为每个数组项进行http服务调用,并将该observable的结果分配给属性?

时间:2019-06-09 18:22:47

标签: rxjs observable angular-httpclient

基本上,我正在尝试从2个端点轮询数据以收集比赛中的参与者。我的服务中有2种方法,它们使用有角度的http-client发出api请求并返回Observables。第一种方法获取一个ID数组,并为传递的每个ID取回一组基本参与者数据(名称,经过时间,当前检查点),第二种方法获取一个ID并从每个检查点返回结果数组给那个参与者

我有一个Observable,它是第一个服务调用的结果。然后,我对其进行管道和映射,以便可以使用数组,然后执行标准的javascript数组映射来迭代元素。我真正坚持的一点是针对匹配条件的数组中的每个“参与者”,我需要对第二个端点进行进一步的http调用,并将可观察到的结果的值分配给参与者的属性。理想情况下,原始的Observable将在可用时立即返回,然后在api调用完成时,该结果数组中的每个参与者将使用检查点结果进行更新。

我才刚刚开始学习rxjs,angular和ngrx,但我仍然在Observable流中挣扎,但是我有一个看起来像这样的ngrx效果

  @Effect()
  pollDataForCollection$ = this.collectionEventsActions$.pipe(
    ofType(CollectionActions.onCountdownRestarted.type),
    withLatestFrom(
      this.featuresStore$.select(collectionSelectors.selectAllFavourites),
      this.featuresStore$.select(collectionSelectors.selectExpandedFavourites)
    ),
    switchMap(([action, faves, expandedDetailIds]) => {
      const ids: number[] = faves.map(fave => fave.id);
      return this.apiService.getParticipantsById(ids).pipe(
        map((participants: Participants[]) => {
          return participants.map(participant => {
            if (expandedDetailIds.includes(participant.id)) {
              this.apiService.getParticipantDetailResults(participant.id).pipe(
                map((results: ParticipantResults[]) => {
                  return (participant.results = results);
                })
              );
            }
            return participant;
          });
        }),
        map(updates => {
          debugger;
          return CollectionActions.pollingDataSucceeded({ items: updates });
        }),
        catchError(error => of(CollectionActions.pollingDataErrored({ error })))
      );
    })
  );

这成功地将参与者和项目数组吸引到每个参与者,但是毫不奇怪,它没有为参与者分配结果。

更新以包含有效的解决方案

非常感谢@ user2216584的解决方案

  @Effect()
  pollDataForCollection$ = this.collectionEventsActions$.pipe(
    ofType(
      CollectionActions.onCountdownRestarted.type
    )
    , withLatestFrom(
      this.featuresStore$.select(collectionSelectors.selectAllFavourites)
    )
    , switchMap(([action, faves]) => {
      const ids: number[] = faves.map(fave => fave.id);
      return this.apiService.getParticipantsById(ids);
    })
    , withLatestFrom(
      this.featuresStore$.select(collectionSelectors.selectExpandedFavourites)
    )
    , switchMap(([participants, expandedFaves]) => {
      const favesWithDetailedResults = participants.map(participant => {
        if(expandedFaves.includes(participant.id)){
            return this.apiService.getParticipantCheckpointResults(participant.id).pipe(
              map((checkpointResults: ParticipantCheckpoint[]) => {
                const participantDetail: Participant = {
                  ...participant,
                  checkpoints: checkpointResults
                }
                return participantDetail;
              })
            )
        }else{
            return of(participant)
        }
      });

      return forkJoin(favesWithDetailedResults)
    })
    , map((updates) => {
      return CollectionActions.pollingDataSucceeded({ items: updates })
    })
    , catchError(error =>
      of(CollectionActions.pollingDataErrored({ error }))
    )
  );

1 个答案:

答案 0 :(得分:0)

这是您需要做的- 对于每个参与者,您需要从详细信息api收集可观察对象并将其推送到数组。该数组应该是可观察值的集合。然后在forJoin的{​​{1}}函数中使用此数组。请参阅以下代码

rxjs