微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用MergeMap调用多个api并订阅数据 更新:API 调用对象中的多个属性

如何解决使用MergeMap调用多个api并订阅数据 更新:API 调用对象中的多个属性

我需要调用一个 api,它将返回一个对象数组。然后我需要遍历所有对象并使用每个对象的 id 来调用一个 api。然后我计划将数据保存在一个数组中并订阅,以便我可以访问包含来自两个 api 调用的数据的自定义数组。但是它对我不起作用。

我需要来自两个 api 调用的组合数据,但是在我创建的结果数组中,来自第二个 api 的数据显示为可观察的,当我尝试使用它们时,我收到未定义的错误。任何帮助将不胜感激。

   this.apiService.getIntakeEvents(90430)
.pipe(mergeMap((res: any)=>{
  const allData =[];
  for(const item of res) {
    let courseInfo = this.apiService.getSpecificCourse(item.courseId)
    allData.push({...item,courseInfo})
  }
  console.log(allData)
  return allData;
}))
.subscribe(res=> console.log(res))

解决方法

我们需要使用几个 RXJS 运算符来获得您想要的。

  • 我们可以使用 mergeMap 来展平内部 observable
  • 然后我们使用 combineLatest 获取每个 API 调用的最新结果
  • 然后我们在每个单独的 API 调用中使用 map 来返回 item 及其相关的 courseInfo
this.apiService
      .getIntakeEvents(90430)
      .pipe(
        mergeMap((items) => {
          return items.map((item) =>
            this.apiService.getSpecificCourse(item.courseId).pipe(
              map((courseInfo) => {
                return {
                  item,courseInfo,};
              })
            )
          );
        })
      )
      .subscribe((res) => console.log(res));
,

您需要使用 forkJoincombineLatestzip 等组合运算符来并行触发多个 observable。鉴于这是一个 API 调用,我认为 forkJoin 更适合这里,因为它仅在所有源完成后才发出。与他们here的短暂区别。

您还需要使用 Array#map 将对象数组转换为 HTTP 调用数组。之后,您可以使用 RxJS map 运算符对每个源 observable 转换回具有修改后的 courseInfo 属性的对象。

this.apiService.getIntakeEvents(90430).pipe(
  mergeMap((res: any) => 
    forkJoin(
      res.map(item => this.apiService.getSpecificCourse(item.courseId)).pipe(
        map(courseInfo => ({ ...item,courseInfo: courseInfo }))
      )
    )
  )
).subscribe(
  next: (res: any) => {
    console.log(res)
  },error: (error: any) => {
    // handle error
  }
);

更新:API 调用对象中的多个属性

要从外部 observable 更新对象中的多个属性,您可能必须使用包裹在外部 forkJoin 中的多个 forkJoin。这当然只是一种方法,可能还有其他更好的方法。

示例

this.apiService.getIntakeEvents(90430).pipe(
  mergeMap((res: any) => 
    forkJoin({
      courses: forkJoin(res.map(item => this.apiService.getSpecificCourse(item.courseId))),names: forkJoin(res.map(item => this.apiService.getSpecificName(item.courseId))),ages: forkJoin(res.map(item => this.apiService.getSpecificAge(item.courseId)))
    }).pipe(map(({courses,names,age}) => 
      res.map((item,index) => ({
        ...item,courseInfo: courses[index],name: names[index],age: ages[index]
      })
    ))
  )
).subscribe(
  next: (res: any) => {
    console.log(res)
  },error: (error: any) => {
    // handle error
  }
);
,

你将不得不转换

this.apiService.getSpecificCourse(item.courseId);

来自 observable to a promise (您如何操作取决于您的 rxjs 版本,该版本包含在该链接中)。一旦它被转换为承诺,你就可以调用 .then() ,它允许你从回调中返回一个实际值。 observable 只允许您订阅,而不允许您从回调中返回值。

所以如果你有最新的 rxjs。你可以这样做:

let courseInfo = lastValueFrom(this.apiService.getSpecificCourse(item.courseId)).then((info) => info);

我认为应该有效

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。