将 MergeMap 与从另一个可观察对象接收的数据数组一起使用 - RxJs Angular

Using MergeMap with the array of data received from another observable - RxJs Angular

我有一个 fetchDrives 方法,它将 return 一个可观察的对象,订阅后将 return 一个驱动器列表

this.fetchDrives(points).subscribe(drives => {
     console.log(drives);
});

假设我订阅的驱动器阵列看起来像这样

[ {driveId: 1}, {driveId: 2}, {driveId: 3} ]

现在我需要通过将 driveId 传递给每个 api call.I 需要将 driveId 传递给下面的方法一次一个,获取纬度和经度,并将三个调用的结果存储在一个数组中。

this.getLatLong(driveId).subscribe( res => console.log(res))

res 将包含类似 { lat: 12, lon: 54 }

的对象

我不想进行两次订阅,有没有一种方法可以使用 Rxjs 运算符并通过使用先前可观察结果的一次订阅来实现此目的,遍历驱动器数组并调用三次 getLatLong 方法使用 mergeMap 作为调用顺序并不重要并将这三个调用的结果存储在数组中?

我尝试使用扫描运算符循环遍历但无法使用它获得所需的输出

提前感谢您的帮助:)

如果我对您的问题的理解正确,您想要展平驱动器阵列以迭代每个驱动器,然后进行 API 调用以获取每个驱动器的经纬度。

你可以用 mergeAllmergeMap 运算符实现这样的事情。
您的代码应如下所示:

fetchDrives().pipe(
  mergeAll(), // Flatten the drives array
  mergeMap(drive => getLatLong(drive)) // Get each drive { lat, lon }
).subscribe(console.log)

您可以 运行 this stackblitz

中的完整示例

如果请求的顺序无关紧要,您可以使用 RxJS forkJoin method to make the calls simultaneously. I've also used switchMap 运算符在源可观察对象 (this.fetchDrives(points)) 发出后切换可观察对象。尝试以下

locations: any;

this.fetchDrives(points).pipe(
  switchMap((drives) => {
    let source = Object.create(null);
    for (let i = 0; i < drives.length; i++) {
      source[drives[i]['driveId']] = this.getLatLong(drives[i]['driveId']);
    }
    return forkJoin(source);
  })
).subscribe(
  response => {
    this.locations = response;
  },
  error => {
    // handle error
  }
);

变量 locations 的形式为

// 'driveId': { lat: 12, lon: 54 }

{
  '1': { lat: 12, lon: 54 },
  '2': { lat: 12, lon: 54 },
  '3': { lat: 12, lon: 54 }
}

更新:对象数组输出

到 return 来自 forkJoin 的对象数组,您可以发送一个可观察对象数组作为参数。例如。 forkJoin([obs1, obs2, ...])。在前面的例子中,我们发送一个对象作为参数 (forkJoin({'name1': obs1, 'name2': obs2, ...}),所以输出也将是一个对象。

locations: any = [];

this.fetchDrives(points).pipe(
  switchMap((drives) => {
    return forkJoin(drives.map(drive => this.getLatLong(drive['driveId'])));
  })
).subscribe(
  response => {
    this.locations = response;
  },
  error => {
    // handle error
  }
);

locations 将采用

形式
[
  { lat: 12, lon: 54 },
  { lat: 12, lon: 54 },
  { lat: 12, lon: 54 }
]