使用 RxJs 时,一个非常常见的问题似乎是希望一个或多个可观察量的结果在后续可观察量中使用它们。
例如在伪代码中(这不是故意的 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);
}
}
这也意味着,在您完成两个可观察量时,没有其他任何东西可以轻松消耗此流。
我的特定用例需要以下内容:
- 获取 $observable-A 的初始调用,因为它不需要任何其他内容(这是一个基本的 http GET 调用(
- 对另一个服务的 http GET 调用,该服务需要来自 $observable-A 的数据,该服务返回 $observable-B
- 使用两个可观察的结果(A + B(为我的服务创建一个对象(在我的例子中,一个Angular服务(以返回单个列表。
还需要能够在我的服务中订阅此功能,这就是为什么使用上面的订阅方法对我不起作用的原因。
Snorre Danielsen解决了这个问题,这个解决方案的全部功劳都归功于他。我建议看看这个。
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 运算符,这不是我们想要的(因为您希望处理pipe
内的常规运算符函数(。
正因为如此,我们可以将这些新合并的可观察量放入链的下一部分,并将它们一起使用。我们使用of()
函数重新创建resultA
,因为combineLatest
只接受可观察量作为输入,并且在此状态下resultA
是一个完整的可观察量。
提示: 看看
map(([resultA, resultB])
.我们使用这种符号来引用我们的变量而不是标准map(results)
的原因。是这样我们就可以直接引用它们,而无需对resultA
使用results[0]
或对resultB
使用results[1]
.以这种方式阅读要容易得多。
我希望这对人们有所帮助,因为我还没有找到涵盖此案的完整 SO 答案。非常欢迎编辑,因为它很复杂,我相信这不是一个完美的答案。