是否有一个可用作concatMap的运算符,但具有多个内部可观察对象

时间:2019-04-07 22:16:13

标签: typescript rxjs

我正在使用可观察的查询我的数据库。 此可观察对象将返回一个包含所有找到的匹配对象的数组。 我的问题是我想将可观察对象与将从另一个API检索的更多详细信息进行映射。

我尝试了concatMap,但它只允许我将1个可观察的嵌套在初始可观察的内部

const usersAPI$: Observable<Users[]> = //  something
const assistsAPI$: Observable<Assists[]> = //  something

const modifiedAssists$ = assistsAPI$.find().pipe(
  concatMap(assists =>
    assists.map(assist => usersAPI$.get(assist.userID)
       .pipe(
          map(user => 
            assist = {...assist}, ...{userName: user.userName}
          )
        )
    )
  )
);

您可以在stackblitz上看到类似的工作示例, https://stackblitz.com/edit/rxjs-concatmap-issue-stackoverflow 其中“结果”是使用concatMap和 “ result2”是我期望的非工作方式

3 个答案:

答案 0 :(得分:1)

您必须以某种方式处理内部的Observable数组。您可以根据需要使用viewA.isHidden = true forkJoinmerge

forkJoin

concat将并行处理内部API调用,并在所有API调用完成后返回一个数组。注意内部的Observable必须完成。我认为这应该适合您的应用程序。

forkJoin

合并

import { forkJoin } from 'rxjs'; const modifiedAssists$ = assistsAPI$.find().pipe( concatMap(assists => forkJoin(assists.map(assist => someObservable )) ); 将立即订阅所有内部API调用,并在所有调用到达时逐一发出结果。

merge

这将使您的stackblitz获得理想的结果,但是我认为您的stackblitz有点误导,而不是您在问题示例代码中寻找的内容,因为stackblitz中的内部Observable会发出多次,并且最终输出不是数组。如果内部请求的顺序无关紧要,它们都将发出一个值,然后完成,您需要将所有请求的结果作为数组,只需使用import { merge } from 'rxjs'; const modifiedAssists$ = assistsAPI$.find().pipe( concatMap(assists => merge(...assists.map(assist => someObservable )), // toArray() add the toArray operator if you need the result as an array );

concat

forkJoin将一个接一个地订阅所有内部API调用。序列中的下一个Observable仅在上一个完成后才订阅。因此,执行将比使用concatforkJoin慢,因为下一个HTTP请求仅在前一个返回值之后才执行。如果对您的merge的调用必须与数组中的userAPI相同,请使用此命令。

assists

答案 1 :(得分:0)

您可以使用combineLatest()(作为静态非管道导入)

import {combineLatest} from 'rxjs';

const usersAPI$: Observable<Users[]> = //  something
const assistsAPI$: Observable<Assists[]> = //  something

const combinedObservable$ = combineLatest(usersAPI$,assistsAPI$, someOtherStuff$);

const modifiedAssists$ = combinedObservable$.pipe(
   map([usersApiValues, assistsAPIValues, someOtherStuffValues] => { 
      /** what you want here */
   }) 
);

只需考虑,combineLatest 中的每个可观察对象应该至少发射一次(例如,您可以使用一个空数组作为开始)

答案 2 :(得分:0)

我相信您想要mergeMap

它将每个外部发射的外部可观测值映射到解析的内部可观测值。

const result = clicks.pipe(
  concatMap(ev =>
    interval(1000).pipe(take(4))
  )
);

const result2 = clicks.pipe(
  mergeMap(ev =>
    arr.map(() => interval(1000).pipe(take(4)))
  )
);
result.subscribe(x => {
  console.log(x)
});

result2.subscribe(x => {
  console.log(x)
});