如何在嵌套的foreach中继续操作之前确保所有异步调用完成

曼努埃尔·纳瓦罗(Manuel Navarro)

首先,我知道这已经被回答过很多次了,但是我一直无法找到如何针对这种特定情况实现它。

一方面,我有一种与此类似的方法

getSomeInfoFromAnApi(param1: number, param2: number): Observable<any> {
    // Call some REST API and return an Observable
  }

另一方面,该方法将以这种方式在其他地方调用:

data.forEach(graphic =>
      graphic.series.forEach(serie => {       
        if (serie.channelValueType === 'string') {
          this.myService.getSomeInfoFromAnApi(graphic.modelId, serie.channelId).subscribe(myResponse => {
            // this is much more complex, just keeping it small for the sake of the example
            // but the important thing here is that a member of the 'serie' item is being modified
            serie.points = myResponse;
          });
        }

      })
    );

// graphics$ is defined as a BehaviorSubject
this.graphics$.next(data);

这里的问题是对BehaviorSubject的next的调用发生的时间比应该发生的要早得多,因为getSomeInfoFromAnApi是一个异步调用。

确保调用仅在处理完数据集合中的所有元素之后才发生的最佳方法是什么,这意味着对getSomeInfoFromAnApi的所有可能的调用都已响应并执行了预订的代码。

初始方法

根据我在stackoverflow上找到的一些答案,这是我到目前为止已经实现的方法,但是我敢肯定必须有一个更好的方法:

data.forEach((graphic, dataIndex) =>
      graphic.series.forEach((serie, seriesIndex) => {     
        
        if (serie.channelValueType === 'string') {
          this.myService.getSomeInfoFromAnApi(graphic.modelId, serie.channelId).subscribe(myResponse => {
            
            // this is much more complex, just keeping it small for the sake of the example
            // but the important thing here is that a member of the 'serie' item is being modified
            serie.points = myResponse;

            if(data.length === dataIndex + 1 && graphic.series.length === seriesIndex + 1) {
              this.graphics$.next(data);
            }
          });
        }
        else {
          if(data.length === dataIndex + 1 && graphic.series.length === seriesIndex + 1) {
            this.graphics$.next(data);
          }
        }

      })
比兹鲍勃

我认为类似这样的方法可能会适合您的情况。

除了使用BehaviorSubject并手动将其发送到该流中之外,我们还可以根据您的data使用创建一个流,from()以分别发出数组项,用于mergeMap()处理订阅您的api调用,然后用于toArray()在所有调用完成后将所有结果合并到一个数组中完成。

graphics$ = from(data).pipe(
  mergeMap(graphic => from(graphic.series).pipe(
    filter(series => series.channelValueType === 'string'),
    mergeMap(series => this.myService.getSomeInfoFromAnApi(graphic.modelId, series.channelId).pipe(
      map(myResponse => ({...series, points: myResponse}))
    ),
  ),
  toArray()
)

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

循环中的所有异步调用完成后,如何调用函数?

如何等待所有异步调用完成

在所有异步HTTP调用完成之前如何显示加载指示器-Angular

我如何知道页面上的所有异步调用何时完成(Parse Cloud函数)?

你如何等待所有异步调用在Java中完成?

多个嵌套的forEach循环中的所有异步操作完成后,如何解决Promise?

如何确保在所有异步函数完成后再次调用间隔函数?

提交表单之前,请等待异步调用完成

在React渲染之前等待多个异步调用完成

当我知道所有异步调用都已完成时,如何运行回调?

Qt异步调用:如何在异步调用完成其工作后运行某些内容

节点在执行代码之前等待所有异步调用

如何知道所有异步HTTP调用已完成

如何异步调用方法并等待API调用完成

异步调用完成后如何访问Set

等待多个异步调用完成?

Java EJB @Asynchronous循环-在继续进行操作之前如何知道所有调用何时完成?

如何进行多个异步调用,然后在所有调用完成后执行一个函数?

如何确保所有异步功能在执行延迟之前运行

等待多个异步调用完成后再继续

Node.js-等待多个异步调用完成,然后继续执行代码

在加载数据之前完成所有异步请求?

量角器 - 在执行 expect 之前等待异步调用完成

Xamarin表单页面在异步调用完成之前不会加载

Javascript - 在从函数返回之前等待异步调用完成,不使用回调

在运行视图控制器 (Swift) 的“覆盖”功能之前等待异步调用完成

如何使Jest在期待断言之前等待所有异步代码完成执行

仅当来自服务的异步调用完成时,如何调用函数?

在运行下一个代码之前,如何等待异步JSZip .forEach()调用完成?