typescript - 是否有一个操作符可以用作 concatMap 但具有多个内部可观察对象
问题描述
我正在使用 observable 来查询我的数据库。这个 observable 将返回一个包含所有找到的匹配对象的数组。我的问题是我想用我将从另一个 API 检索到的更多细节来映射 observable。
我尝试了 concatMap 但它只让我将 1 个 observable 嵌套在初始 observable 中
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 的正确方法,而“结果 2”是不工作的我期望的工作方式
解决方案
你必须以某种方式处理你内部的 Observable 数组。您可以使用forkJoin
,merge
或concat
根据您的需要。
分叉加入
forkJoin
将并行处理您的内部 API 调用,并在所有 API 调用完成后返回一个数组。请注意,内部的 Observables 必须完成。我认为这应该适合您的应用程序。
import { forkJoin } from 'rxjs';
const modifiedAssists$ = assistsAPI$.find().pipe(
concatMap(assists => forkJoin(assists.map(assist => someObservable ))
);
合并
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
);
这将为您的 stackblitz 提供所需的结果,但我认为您的 stackblitz 有点误导,而不是您在问题的示例代码中寻找的内容,因为您的 stackblitz 中的内部 Observable 多次发出并且最终输出是不是一个数组。如果内部请求的顺序无关紧要,它们都会发出一个值然后完成,您需要将所有请求的结果作为一个数组,只需使用forkJoin
.
连接
concat
将一个接一个地订阅所有内部 API 调用。序列中的下一个 Observable 只有在前一个完成后才会被订阅。因此,执行将比 with 慢,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
);