【问题标题】:RXJS How do I use the result of one observable in another (and then process those two results together)RXJS 如何在另一个中使用一个 observable 的结果(然后将这两个结果一起处理)
【发布时间】:2020-09-20 07:26:53
【问题描述】:

使用 RxJs 时一个非常常见的问题似乎是希望一个或多个 observables 的结果然后在后续的结果中使用它们。

例如在伪代码中(这不是 rx 或故意的有效 js 语法)

var someResult = $observable-A; // wait to complete
var finalResult = $observable-B(someResult.aValueINeed);

这可以通过一种丑陋的方式来完成,您可以同时订阅两者并在另一个内部调用一个。但是,这非常混乱并且不能为您提供太大的灵活性。

例如(真正的语法)

$observable-A.subscribe(resultA => { 
    $observable-B(resultA.aValueINeed)
        .subscribe(resultB => { 
            console.log('After everything completes: ', resultB); 
        }
}

这也意味着当你完成两个 observables 时,没有其他东西可以轻易地消耗这个流。

我的具体用例需要以下内容:

  1. 获取 $observable-A 的初始调用,因为它不需要任何其他内容(这是一个基本的 http GET 调用)
  2. 对另一个服务的 http GET 调用需要来自 $observable-A 的数据,该数据返回 $observable-B
  3. 使用两个可观察结果 (A + B) 为我的服务(在我的例子中是 Angular 服务)创建一个对象以返回一个列表。

我还需要能够在我的服务中订阅此功能,这就是为什么使用上面的订阅方法对我不起作用。

【问题讨论】:

    标签: angular rxjs rxjs6 rxjs-pipeable-operators


    【解决方案1】:

    Snorre Danielsen 解决了这个问题,这个解决方案的全部功劳归于他。我建议看看this

    rxjs 运算符的优点在于它们的互操作性。您可以混合搭配几乎所有东西以获得您想要的结果。

    简而言之。这个问题的代码答案如下,我会进一步解释。

    $observable-A.pipe(
        mergeMap(resultA => {
            return combineLatest(
                of(resultA),
                $observable-B(resultA)
            )
        }),
        map(([resultA, resultB]) => {
            // you can do anything with both results here
            // we can also subscribe to this any number of times because we are doing all the processing with
            // pipes and not completing the observable
        }
    )
    

    mergeMap(或别名flatMap)将可观察对象作为输入并将其投影(就像常规映射函数一样)。这意味着我们可以将其结果用作$observable-B 的输入。现在,当您实际上只想返回第二个可观察结果时,这非常有用。例如

    $observable-A.pipe(
        mergeMap(resultA => $observable-B(resultA)),
        map((resultB) => {
            // resultA doesn't exist here and we can only manipulate resultB
        }
    )
    
    

    现在,回到主要解决方案。 combineLatest 是这里的关键。它允许mergeMap 基本上“等待”内部可观察对象 ($observable-B) 完成。 没有它,你只会在pipe 中向你的下一个 rxjs 运算符返回一个 observable,这不是我们想要的(因为你希望在 pipe 中处理常规运算符函数)。

    因此,我们可以将这些新合并的 observables 带入链的下一部分,并一起使用它们。我们使用of() 函数重新创建resultA,因为combineLatest 只接受observables 作为输入,resultA 在这个状态下是一个完成的observable。

    提示: 看看map(([resultA, resultB])。我们使用这个符号来引用我们的变量而不是标准的map(results) 的原因。这样我们就可以直接引用它们,而无需将results[0] 用于resultAresults[1] 用于resultB。以这种方式阅读会容易得多。


    我希望这对人们有所帮助,因为我还没有找到涵盖此案例的完整 SO 答案。编辑非常受欢迎,因为它很复杂,我敢肯定它不是一个完美的答案。

    【讨论】:

    • 如果两个 observables 都来自 HTTP 请求,switchMapforkJoin 将比 mergeMapcombineLatest 更合适。合并来自多个请求的结果并不常见。 combineLatestzip 运算符有非常具体的用例,在这些用例中,您需要源 observables 中的值一旦发出(假设所有源都至少发出一次)。
    • 有意思,为什么会这样?
    • mergeMap 用于合并来自可观察源的多个通知。在 HTTP 中很少出现这种情况。有关高阶映射运算符的信息,请参阅here。至于combineLatest,它用于从一个不立即完成的数据流中获取结果。但是 HTTP observables 发出一次并立即完成,这是forkJoin 的特定情况。它仅在可观察对象完成后发出。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-21
    • 1970-01-01
    • 2022-06-23
    • 2021-02-05
    • 1970-01-01
    • 2019-01-23
    • 2020-10-02
    相关资源
    最近更新 更多