是否有一个操作符可以用作 concatMap 但有多个内部可观察对象 [英] Is there an operator that works as concatMap but with more than one inner observables

查看:34
本文介绍了是否有一个操作符可以用作 concatMap 但有多个内部可观察对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 observable 来查询我的数据库.这个 observable 将返回一个包含所有找到的匹配对象的数组.我的问题是我想用我将从另一个 API 检索的更多细节来映射 observable.

I'm using an observable to query my DB. This observable will return an array with all the matching objects found. My problem is that I want to map the observable with more details that I will retrieve from another API.

我尝试了 concatMap 但它只让我在初始 observable 中嵌套 1 个 observable

I tried concatMap but it only let me nest 1 observable inside the initial 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 的正确方法,而result2"是我期望的非工作方式

You can see a similar working example here, on stackblitz, https://stackblitz.com/edit/rxjs-concatmap-issue-stackoverflow where the "result" is the correct way of using concatMap and the "result2" is the non working way that I expected to work

推荐答案

您必须以某种方式处理内部的 Observable 数组.您可以根据需要使用 forkJoinmergeconcat.

You have to process your inner array of Observables in some way. You could use forkJoin, merge or concat depending on your needs.

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

forkJoin will process your inner API calls in parallel and return an array when all API calls complete. Note that the inner Observables have to complete. I think this is what should suit you in your app.

import { forkJoin } from 'rxjs';

const modifiedAssists$ = assistsAPI$.find().pipe(
  concatMap(assists => forkJoin(assists.map(assist => someObservable ))
);

合并

merge 将一次订阅所有内部 API 调用,并在所有调用到达时一一发出结果.

merge

merge will subscribe to all inner API calls at once and emit the results of all calls one by one as they arrive.

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.

This will give you the desired result in your stackblitz, but I think your stackblitz is somewhat missleading and not what you're looking for in the example code from your question, as the inner Observable in your stackblitz emits multiple times and the final output isn't an array. If the order of the inner requests doesn't matter, they all emit one value and then complete and you need the results of all request as an array just use forkJoin.

concat 将订阅所有内部 API 调用一个接一个.序列中的下一个 Observable 只会在前一个完成后订阅.因此,执行将比 forkJoinmerge 慢,因为下一个 HTTP 请求只会在前一个返回值后执行.如果对 userAPI 的调用必须按照与数组中的 assists 相同的顺序进行.

concat will subscribe to all inner API calls one after another. The next Observable in the sequence will only be subscribed to after the previous completed. The execution will therefore be slower than with forkJoin or merge as the next HTTP request will only be executed after the previous returned a value. Use this if the calls to your userAPI specifically have to be made in the same order as the assists in your array.

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
);

这篇关于是否有一个操作符可以用作 concatMap 但有多个内部可观察对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆