【问题标题】:RxJS: SwitchMap for Array of StringsRxJS:字符串数组的 SwitchMap
【发布时间】:2021-08-18 01:25:12
【问题描述】:

以下用例:用户可以加入 0...* 个组。每个组都有一个 ID 并包含 0...* 个帖子。

我订阅了一个 Observable(以获取他加入的用户的群组),这将返回一个字符串数组(群组 ID)。

const groupIds$ = of(['a', 'b', 'c']);

如果我只有一个,我现在会使用 switchMap 并返回这个新的 observable 并订阅它以从群组中获取帖子。

但是我有一个数组,所以这不起作用。有谁知道哪个 RxJS 操作员可以实现这一点以获取所有组的帖子?

或者这种用例不存在运营商,我必须在订阅时单独进行?

【问题讨论】:

  • 我不知道你想做什么。您想为groupIds$ 中的每个项目创建一个 Observable 并订阅所有项目吗?或者您只想订阅最先发出的那个?
  • 第一个:我想为 groupIds$ 中的每个项目创建一个 Observable 并订阅所有这些项目。正如我所说,如果我只有一个,我会使用 switchMap 并订阅那个新的 observable,但是使用字符串数组这是不可能的

标签: rxjs


【解决方案1】:

如果您知道将所有源 Observables 作为一个数组,您可以理想地使用 forkJoin

groupIds$.pipe(
  concatMap(groups => {
    const observables = groups.map(id => ...);
    return forkJoin(...observables);
  })
).subscribe(...);

forkJoin 将发出一个数组,其中所有结果的顺序与groupIds$ 中的顺序相同。

最终,如果您不关心订单并且只想并行获取所有结果,您可以使用merge 而不是forkJoin(我的意思是“可观察的创建方法”称为merge 直接从rxjs。不是来自'rxjs/operators'merge 运算符)。

【讨论】:

  • forkJoin 不起作用,因为它仅在 observable 完成时才发出。我的 Observable 没有完成,因为如果该组有新帖子到达,它将被发出。但合并似乎正在工作:) 谢谢!我使用 switchMap 而不是 concatMap ;)
【解决方案2】:

遇到这个问题的每个人,这里是“用于字符串数组的 switchMap”的答案(感谢马丁)。你只需要使用'rxjs'中的'merge'(而不是操作员!)。在 switchMap 内部返回合并,你就完成了:

groupIds$.pipe(
    switchMap(groups => {
        const observables = groups.map(id => {
            // your function that returns the observable
            return something.getObservable(id);
        });
        return merge(...observables);
    })
).subscribe(data => {
    console.log('DATA', data);
});

【讨论】:

    【解决方案3】:

    可能的解决方案:https://www.learnrxjs.io/operators/transformation/mergemap.html

    const groupIds$ = of(['a', 'b', 'c']);
    
    const myPromise = id =>
      new Promise(resolve => resolve(something.getPostsByGroupId(id)));
    
    const posts$ = groupIds$.pipe(
      mergeMap(
        id => myPromise(id),
        (valueFromSource, valueFromPromise) => {
          return valueFromPromise;
        }));
    
    posts$.subscribe(...);
    

    【讨论】:

    • 这不起作用,因为来自mergeMap(id => {...}) 的“id”仍然是一个数组
    • 只有在我有最终值的情况下才有效,但我的 observable 是一个不完整的流,但我已经找到了解决方案 -> stackoverflow.com/a/53286688/8971128
    【解决方案4】:

    Terser 对现有答案的改进。 每次groupIds$ 源发出时,它都会发出一个包含所有帖子的数组。

    groupIds$.pipe(
      switchMap(ids => zip(...ids.map(id => service.getPosts(id)))),
      map((posts: Array<Post[]>) => [].concat.apply([], posts))
    ).subscribe(posts => /*is an array of all posts*/);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-02
      • 1970-01-01
      • 1970-01-01
      • 2022-01-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多