【问题标题】:rxjs - combining inner observables after filteringrxjs - 过滤后组合内部可观察对象
【发布时间】:2018-08-29 15:33:34
【问题描述】:

我调用后端响应:

[
  "https://some-url.com/someData1.json",
  "https://some-url.com/someData2.json"
]

每个 JSON 可以有以下架构:

{
  "isValid": boolean,
  "data": string
}

我想获取所有数据的数组,将 isValid 设置为 true

backend.get(url)
    .pipe(
        mergeMap((urls: []) =>
            urls.map((url: string) =>
                backend.get(url)
                    .pipe(
                        filter(response => response.isValid),
                        map(response => response.data)
                    )
            )
        ),
        combineAll()
    )

当两个 .json 都将“isValid”设置为 true 时,我会得到包含两个数据的数组。 但是当其中一个将“isValid”设置为 false 时,可观察到的永远不会完成。

我可以使用 mergeAll 而不是 combineAll,但随后我会收到单个数据流而不是所有数据的集合。

有没有更好的方法来过滤掉 observable?

【问题讨论】:

    标签: rxjs rxjs6


    【解决方案1】:

    正如你所说,内部 observable 永远不会发出,因为 filter 不会转发 backend.get observable 发出的唯一值。在这种情况下,订阅该 observable 的操作员 - 在您的情况下为 combineAll - 也将永远不会收到任何值,也永远不会发射自己。

    我要做的只是通过提供一个项目功能将过滤和映射移动到combineAll,如下所示:

    backend.get(url)
        .pipe(
            mergeMap((urls: string[]) =>
                urls.map((url: string) => backend.get(url))
            ),
            combineAll(responses =>
                responses
                    .filter(response => response.isValid)
                    .map(response => response.data)
            )
        )
    

    看看这是否适合你;)

    【讨论】:

    • 谢谢,事实上过滤将在另一个 Observable 产生后进行,这就是为什么我想要清除 combineAll 并考虑过滤掉 Observable 但似乎使用 combineAll 不是一个好主意:)跨度>
    【解决方案2】:
    import { forkJoin, Observable } from 'rxjs';
    import { map } from 'rxjs/operators';
    
    interface IRes {
      isValid: boolean;
      data: string;
    }
    
    interface IResValid {
      isValid: true;
      data: string;
    }
    
    function isValid(data: IRes): data is IResValid {
      return data.isValid;
    }
    
    const res1$: Observable<IRes> = backend.get(url1);
    const res2$: Observable<IRes> = backend.get(url2);
    
    // When all observables complete, emit the last emitted value from each.
    forkJoin([res1$, res2$])
      .pipe(map((results: IRes[]) => results.filter(isValid)))
      .subscribe((results: IResValid[]) => console.log(results));
    

    【讨论】:

    • 这可能是一个正确的答案,但可以通过添加对它的作用以及它如何回答问题的描述来改进它。欲了解更多信息,请阅读stackoverflow.com/help/how-to-answer
    猜你喜欢
    • 2018-11-23
    • 2016-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多