简体   繁体   English

使用 flatMap 链接 observables

[英]Chaining observables with flatMap

I'm working with observables and the flatMap operator, I wrote a method which makes and API call and returns an observable with an array of objects.我正在使用 observables 和 flatMap 运算符,我编写了一个方法,该方法进行 API 调用并返回一个带有对象数组的 observable。

Basically what I need is to get that array of objects and process each object, after all items are processed.基本上我需要的是在处理所有项目之后获取该对象数组并处理每个对象。 I want to chain the result to make an extra API call with another method that I wrote.我想链接结果以使用我编写的另一个方法进行额外的 API 调用。

The following code does what I need:下面的代码做我需要的:

  this.apiService.getInformation('api-query', null).first().flatMap((apiData) => {
    return apiData;
  }).subscribe((dataObject) => {
    this.processService.processFirstCall(dataObject);
  }, null, () => {
    this.apiService.getInformation('another-query', null).first().subscribe((anotherQueryData) => {
      this.processService.processSecondCall(anotherQueryData);
    });
  });

But this approach isn't optimal from my perspective, I would like to do chain those calls using flatMap but if I do the following:但是从我的角度来看,这种方法并不是最佳的,我想使用 flatMap 来链接这些调用,但是如果我执行以下操作:

   this.apiService.getInformation('api-query', null).first().flatMap((apiData) => {
    return apiData;
  }).flatMap((dataObject) => {
    this.processService.processFirstCall(dataObject);
    return [dataObject];
  }).flatMap((value) => {
    return this.apiService.getInformation('another-api-query', null).first();
  }).subscribe((value) => {
    this.processService.processSecondCall(value);
  });

The second API call executes once for each item on the apiData array of objects.第二个 API 调用对 apiData 对象数组上的每个项目执行一次。 I know I'm missing or misunderstanding something.我知道我遗漏或误解了某些东西。 But from the second answer of this thread Why do we need to use flatMap?但是从这个线程的第二个答案为什么我们需要使用 flatMap? , I think that the second flatMap should return the processed apiData, instead is returning each of the object items on that Array. ,我认为第二个 flatMap 应该返回处理后的 apiData,而不是返回该 Array 上的每个对象项。 I would appreciate the help.我将不胜感激。

Thank you.谢谢。

What you want is the .do() operator, and not flatMap() .您想要的是.do()运算符,而不是flatMap() flatMap() is going to transform an event to another event, and in essence, chaining them. flatMap()将一个事件转换为另一个事件,本质上是将它们链接起来。 .do() just executes whatever you instruct it to do, to every emission in the events. .do()只是执行你指示它做的任何事情,对事件中的每个发射。

From your code, there are 2 asynchronous methods (calls to the api) , and 2 synchronous (processService).从您的代码中,有 2 个异步方法(调用 api)和 2 个同步方法(processService)。 What you want to do is :你想要做的是:

  1. Call to the first API (async), wait for the results调用第一个API(异步),等待结果
  2. Process the results (sync)处理结果(同步)
  3. Call to the second API (async), wait for the results to come back调用第二个API(异步),等待结果回来
  4. Process the results (sync)处理结果(同步)

Hence your code should be :因此你的代码应该是:

this.apiService.getInformation('api-query', null)//step1
    .first()
    .do((dataObject) => this.processFirstCall(dataObject))//step2
    .flatMap(() => this.apiService.getInformation('another-api-query', null))//step3
    .first()
    .do(value => this.processService.processSecondCall(value))//step4
    .subscribe((value) => {
        console.log(value);
    });

I wrote in comment the steps corresponding to the list above.我在评论中写了与上面列表相对应的步骤。 I also cleaned up unnecessary operators (like your first flatMap is kinda redundant).我还清理了不必要的操作符(比如你的第一个flatMap有点多余)。

Also, in the event you want to transform your data, then you should use .map() instead of .do() .此外,如果您想转换数据,则应使用.map()而不是.do() And I think that is the place where you are confused with .map() and .flatMap() .我认为这是您与.map().flatMap()混淆的地方。

The issue I think your encountering is that flatmap should be applied to an observable or promise.我认为您遇到的问题是应该将 flatmap 应用于 observable 或 promise。 in your second code example, you are returning data within the flatmap operator which is then passed to the following flatmap functions, whereas these should be returning observables.在您的第二个代码示例中,您将在 flatmap 运算符中返回数据,然后将其传递给以下 flatmap 函数,而这些应该返回可观察对象。 For example:例如:

this.apiService.getInformation('api-query', null).first()
  .flatMap((dataObject) => {
    return this.processService.processFirstCall(dataObject);
  }).flatMap((value) => {
    return this.apiService.getInformation('another-api-query', null)
  }).subscribe((value) => {
    this.processService.processSecondCall(value);
  });

See this post for futher clarification.请参阅此帖子以获取进一步说明。

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

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