简体   繁体   English

将 MergeMap 与从另一个 observable 接收的数据数组一起使用 - RxJs Angular

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

I have a fetchDrives method which will return an observable which on subscription will return a list of drives我有一个 fetchDrives 方法,它会返回一个 observable,订阅时会返回一个驱动器列表

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

Assume The drives array which I got on subscription look some what like this假设我订阅的驱动器阵列看起来像这样

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

Now I need to use the driveId one by one and make three calls ( three because length of the drives array is 3 ) by passing driveId to each api call.I need to pass driveId to the below method one at a time and get the lat and lon and store the result of three calls in an array.现在我需要通过将 driveId 传递给每个 api 调用来逐个使用 driveId 并进行三个调用(三个调用,因为驱动器数组的长度为 3)。我需要一次将 driveId 传递给以下方法并获取 lat和 lon 并将三个调用的结果存储在一个数组中。

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

The res will contain an object like { lat: 12, lon: 54 } res 将包含一个 object 像{ lat: 12, lon: 54 }

I don't want to do two subscriptions, is there a way I can use the Rxjs operators and achieve this with one subscription using the result of previous observable, loop through the drives array and make three calls to getLatLong method using mergeMap as the sequence of the calls doesn't matter and store the result of those three calls in an array?我不想进行两次订阅,有没有办法可以使用 Rxjs 运算符并使用先前可观察的结果通过一次订阅来实现此目的,循环遍历驱动器数组并使用mergeMap作为序列对getLatLong方法进行三次调用调用无关紧要并将这三个调用的结果存储在数组中?

I tried using scan operator to loop through but failed to use it to get the desired output我尝试使用扫描运算符循环但未能使用它来获得所需的 output

Thanks for the help in advance:)我在这里先向您的帮助表示感谢:)

If I understood your question correctly, you want to flatten drives array in order to iterate each drive, and then make API call to get each drive lat lon.如果我正确理解了您的问题,您想要展平驱动器阵列以迭代每个驱动器,然后进行 API 调用以获取每个驱动器 lat lon。

You can achieve such thing with mergeAll and mergeMap operators.您可以使用mergeAllmergeMap运算符来实现这样的事情。
Your code should look something like this:您的代码应如下所示:

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

You can run the full example in this stackblitz您可以在此 stackblitz中运行完整示例

If the order of the requests doesn't matter, you could use RxJS forkJoin method to make the calls simultaneously.如果请求的顺序无关紧要,您可以使用 RxJS forkJoin方法同时进行调用。 I've also used switchMap operator to switch the observable once the source observable ( this.fetchDrives(points) ) emits.一旦源可观察对象( this.fetchDrives(points) )发出,我还使用switchMap运算符来切换可观察对象。 Try the following尝试以下

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

Variable locations will be of the form可变locations的形式为

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

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

Update: array of objects output更新:对象数组 output

To return an array of objects from forkJoin you could send in an array of observables as the argument.要从forkJoin返回一个对象数组,您可以发送一个可观察对象数组作为参数。 For eg.例如。 forkJoin([obs1, obs2, ...]) . forkJoin([obs1, obs2, ...]) In the previous case we were sending an object as the argument ( forkJoin({'name1': obs1, 'name2': obs2, ...}) , so the output will also be an object.在前面的例子中,我们发送一个 object 作为参数( forkJoin({'name1': obs1, 'name2': obs2, ...}) ,所以 output 也将是一个 ZA8CFDE6331BD59EB26ACZF4 。

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 will be of the form locations将采用以下形式

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM