如何使 concatMap 嵌套
how to make concatMap nested
我需要为数组中的每个原产日期获取一系列数据
我需要按顺序获取它们,所以我使用 concatMap 来查看我的可观察日期,当我获取第一组值时,一切正常
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);
});
我有我的 this.gastoRealizado 阵列
但我需要再调用 3 次后端以获得总共 4 个数组,然后将其提供给图表,但我不知道如何按此既定顺序添加更多调用
有什么想法吗?
谢谢
不确定这是否能回答您的问题(无法post发表评论以询问具体情况)。但假设其他后端调用也仅依赖于 this.etiquetasEjeX
中的元素,您可以使用 zip
运算符。然而,关于 concatMap
的用法,四个请求将在每个项目同时执行。如果您一次只能进行一个 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][])=> {
//...
});
编辑:
好的,您在评论中提到后续请求取决于先前请求的结果。如您在以下示例中所见,像您最初请求的那样嵌套 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
});
但也可以按顺序调用相同的操作,而不会丢失提供图表所需的中间结果:
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;
});
而且我注意到您正在使用 toArray
。这意味着在所有 api 调用完成之前,您的可观察对象不会为您提供任何中间结果。根据您 api 提供的结果数组的大小,给定的解决方案可能非常耗费时间和内存。
我需要为数组中的每个原产日期获取一系列数据
我需要按顺序获取它们,所以我使用 concatMap 来查看我的可观察日期,当我获取第一组值时,一切正常
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);
});
我有我的 this.gastoRealizado 阵列
但我需要再调用 3 次后端以获得总共 4 个数组,然后将其提供给图表,但我不知道如何按此既定顺序添加更多调用
有什么想法吗?
谢谢
不确定这是否能回答您的问题(无法post发表评论以询问具体情况)。但假设其他后端调用也仅依赖于 this.etiquetasEjeX
中的元素,您可以使用 zip
运算符。然而,关于 concatMap
的用法,四个请求将在每个项目同时执行。如果您一次只能进行一个 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][])=> {
//...
});
编辑:
好的,您在评论中提到后续请求取决于先前请求的结果。如您在以下示例中所见,像您最初请求的那样嵌套 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
});
但也可以按顺序调用相同的操作,而不会丢失提供图表所需的中间结果:
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;
});
而且我注意到您正在使用 toArray
。这意味着在所有 api 调用完成之前,您的可观察对象不会为您提供任何中间结果。根据您 api 提供的结果数组的大小,给定的解决方案可能非常耗费时间和内存。