简体   繁体   English

如何使 concatMap 嵌套

[英]how to make concatMap nested

I need to obtain a series of data for each of the dates of origin that I have in an array我需要为数组中的每个原始日期获取一系列数据

大批

and I need to obtain them in order so I use concatMap to go through my observable of dates and when I obtain the first group of values everything goes fine我需要按顺序获取它们,所以我通过我的可观察日期使用 concatMap 到 go 并且当我获得第一组值时一切正常

of(...this.etiquetasEjeX)
  .pipe(
    concatMap(item=>
        this.dataService.getGastadoRealizadoEnMesYAño(this.proyectoId,
        getMonthNumber(item.slice(0,item.length-4)),
        +item.slice(-4),
        this.acumular)
        ),
    toArray()
  )
  .subscribe(item=>{
    this.gastadoRealizado=item;
    console.log('this.gastadoRealizado: ', this.gastadoRealizado);
  });

I have my this.gastoRealizado array我有我的 this.gastoRealizado 数组

胃口大开

but I need to do 3 More calls to the backend to obtain a total of 4 arrays that then feed a graph and I don't know how to add more calls in this established order但我需要对后端进行 3 次以上调用以获得总共 4 次 arrays 然后提供图表,我不知道如何以这个既定顺序添加更多调用

Any idea, please?请问有什么想法吗?

Thanks谢谢

Not sure if this answers your question (couldn't post a comment to ask for specifics).不确定这是否回答了您的问题(无法发表评论以询问具体情况)。 But assuming the other back end calls also depend only on an element from this.etiquetasEjeX you could use the zip operator.但假设其他后端调用也仅依赖于this.etiquetasEjeX中的一个元素,您可以使用zip运算符。 However regarding the usage of concatMap the four request would be performed simultaneously per item.然而,关于concatMap的使用,每个项目将同时执行四个请求。 If you were restricted to one api call at a time this solution would need some adjustments.如果您一次只能调用一个 api,则此解决方案需要进行一些调整。

import { of, zip } from 'rxjs';
import { concatMap, toArray } from 'rxjs/operators';

//...

of(...this.etiquetasEjeX)
  .pipe(
    concatMap(item=>
        zip(
            this.dataService.getGastadoRealizadoEnMesYAño(...),
            this.dataService.getB...,
            this.dataService.getC...,
            this.dataService.getD...,
        ),
    toArray(),
  )
  .subscribe((arr: [ItemA, ItemB, ItemC, ItemD][])=> {
    //...
  });

Edit:编辑:

okay in your comment you mentioned that a subsequent request depends on the result of a prior request.好的,您在评论中提到后续请求取决于先前请求的结果。 Nesting concatMap operations like your initially requested would be a little messy as you can see in the following example:像您最初请求的那样嵌套concatMap操作会有点混乱,您可以在以下示例中看到:

of(...this.etiquetasEjeX)
  .pipe(
    concatMap(item=>
      this.dataService.getGastadoRealizadoEnMesYAño(...).pipe(
        concatMap(itemA =>
          this.dataService.getB(itemA).pipe(
            concatMap(itemB =>
              this.dataService.getC(itemB).pipe(
                concatMap(itemC =>
                  this.dataService.getD(itemC).pipe(
                    map(itemD =>
                      // every combination of items would be available here
                      this.getGraph(item, itemA, itemB, itemC, itemD)
                    )
                  )
                )
              )
            )
          )
        )
      )
    ),
    toArray(),
  )
  .subscribe(graphs => {
    // graphs array contains elements that were returned by this.getGraph 
  });

But the same operations could also be called sequentially without losing the intermediate results that you will need for feeding your graph:但是也可以按顺序调用相同的操作,而不会丢失提供图形所需的中间结果:

of(...this.etiquetasEjeX)
  .pipe(
    concatMap(item=> combineLatest(
      of(item),
      this.dataService.getA(item, ...),
    )),
    concatMap(([item, itemA]) =>
      this.dataService.getB(itemA, ...)
combineLatest(
      of([item, itemA]), // it's important that the elements are enclosed inside an array here otherwise the of operator fires twice and doesn't have the proper effect
      ,
    )),
    concatMap(([prevItems, itemB]) => combineLatest(
      of([...prevItems, itemB]),
      this.dataService.getC(itemB, ...),
    )),
    concatMap(([prevItems, itemC]) => combineLatest(
      of([...prevItems, itemC]),
      this.dataService.getD(itemC, ...),
    )),
    map(([item, itemA, itemB, itemC, itemD]) =>
      this.getGraph(item, itemA, itemB, itemC, itemD)
    ),
    toArray(),
  )
  .subscribe(graphs => {
    // update the state of your object eg.
    this.myGraphs = graphs;
  });

And I noticed that you are using toArray .我注意到您正在使用toArray That means your observable won't provide you with any intermediate results until all your api calls have been finished.这意味着在您完成所有 api 调用之前,您的 observable 不会为您提供任何中间结果。 Depending on the size of the resulting arrays provided by your api the given solution might be quite time and memory consuming.根据您的 api 提供的 arrays 的大小,给定的解决方案可能会花费大量时间和 memory。

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

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