是否有一个运算符可以作为 concatMap 但具有多个内部可观察值

J R*_*nto 8 rxjs typescript

我正在使用可观察的对象来查询我的数据库。该可观察对象将返回一个数组,其中包含找到的所有匹配对象。我的问题是我想将可观察值与我将从另一个 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}
          )
        )
    )
  )
);
Run Code Online (Sandbox Code Playgroud)

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

fri*_*doo 8

你必须以某种方式处理你的内部 Observables 数组。您可以使用forkJoin,mergeconcat根据您的需要。

分叉连接

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

import { forkJoin } from 'rxjs';

const modifiedAssists$ = assistsAPI$.find().pipe(
  concatMap(assists => forkJoin(assists.map(assist => someObservable ))
);
Run Code Online (Sandbox Code Playgroud)

合并

merge将立即订阅所有内部 API 调用,并在所有调用到达时一一发出它们的结果。

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
);
Run Code Online (Sandbox Code Playgroud)

这将为您在 stackblitz 中提供所需的结果,但我认为您的 stackblitz 有点误导,而不是您在问题的示例代码中寻找的内容,因为 stackblitz 中的内部 Observable 发出多次,最终输出是不是一个数组。如果内部请求的顺序无关紧要,它们都会发出一个值,然后完成,并且您需要将所有请求的结果作为数组,只需使用forkJoin.

连接

concat将依次订阅所有内部 API 调用。序列中的下一个 Observable 只会在前一个 Observable 完成后才会被订阅。因此,执行速度将比使用forkJoin或慢merge,因为下一个 HTTP 请求只会在前一个返回值之后执行。userAPI如果对您的调用必须按照与数组中的顺序相同的顺序进行,请使用此选项assists

import { concat } from 'rxjs';

const modifiedAssists$ = assistsAPI$.find().pipe(
  concatMap(assists => concat(...assists.map(assist => someObservable )),
  // toArray() add the toArray operator if you need the result as an array
);
Run Code Online (Sandbox Code Playgroud)