rxjs switchMap 和 tap 问题
rxjs switchMap and tap issue
我正在使用 switchMap 运算符来清楚地了解 "switched" 内部可观察对象发生了什么。
起初我认为 switchMap 只是 "unsubscribing" 来自 switched inner observable,但后来我意识到它实际上是“unsubscribing AND completing” inner observable .
确认我写了这个小片段:
https://codesandbox.io/s/relaxed-meninsky-c5jmw?fontsize=14
如你所见,finalize() operator 在 subject 第二次 emit 时被正确调用,但是:
为什么不调用 tap 运算符的完整处理程序?
不知何故,我对这个运算符的理解只有 80% 的满意度。
相关的不是那个:
我阅读并观看了许多有关 switchMap 的资源,包括:
- 这个(很棒的)ngconf 来源:https://medium.com/@shairez/a-super-ninja-trick-to-learn-rxjss-switchmap-mergemap-concatmap-and-exhaustmap-forever-88e178a75f1b
- 官方 rxjs 文档:https://rxjs-dev.firebaseapp.com/api/operators/switchMap
其中 none 清楚地说明了内部可观察对象是取消订阅还是取消订阅并关闭(或者至少我不明白:))
我看了switchMap算子源码,没有提到takeXXX算子,没有那个他怎么完成内部算子?
tl;dr
- 你确认switchMap在切换时完成了inner observable吗?
- 为什么点击运算符没有按预期工作?
- 如果 switchMap 有效地完成内部 observable,他如何在不使用内部 takeXXX 运算符的情况下做到这一点?
我认为您混淆了 unsubscribe()
和 complete()
之间的区别。对于像 Subject
这样的热门可观察对象,您可以通过几种方式 "stop" 它。从 'top->down' 和 complete()
就像你在你的例子中所做的那样,或者从 'bottom->up' 和 unsubscribe()
.
switchMap()
完全按照它说的去做,它从主要可观察对象切换到次要(或 'inner')可观察对象。这就是为什么当你 complete()
外部 observable 时,它对内部 observable 没有影响 - 链已被切换。要影响链(而不是仅仅影响作为源可观察对象的主题),您需要获得对订阅者的引用,然后调用该订阅者的 unsubscribe()
方法。
为了看到这个,我分叉了你的 CodeSandbox 并制作了这个 new one
正如您将在该 CodeSandbox 中看到的那样,我添加了更多行来显示正在发生的事情:
- 注意链中 switchMap 正上方的新
tap()
- 这将显示在使用 switchMap 运算符将链切换到不同的 Observable 之前直接从 Subject()
发生的事情。
- 链的订阅现在正在变量
sub
中捕获,稍后可以取消订阅以从下到上影响链。
- 请注意,10 秒后的
s.complete()
现在反映在主题中,还要注意它根本不影响链。
- 现在请注意,新的
sub.unsubscribe()
在 15 秒后确实会杀死链条。
- 取消注释
newT()
方法中的 take(5)
以查看如果上面的源实际完成(自上而下),确实会调用 tap 的 complete 方法。
finalize()
捕捉到发生取消订阅的事实(自下而上),请注意,它发生在 switchMap()
向上自动取消订阅和调用 s.next()
时主题源,以及在订阅上调用 unsubscribe()
时,这再次导致自下而上的终止。在任何情况下,您的 complete()
都不会在原始观察者中调用,因为该链从未真正完成。如果需要,您可以使用 take(10)
运算符完成链,看看它是如何工作的。
希望这有助于稍微消除混乱。 :)
我正在使用 switchMap 运算符来清楚地了解 "switched" 内部可观察对象发生了什么。
起初我认为 switchMap 只是 "unsubscribing" 来自 switched inner observable,但后来我意识到它实际上是“unsubscribing AND completing” inner observable .
确认我写了这个小片段: https://codesandbox.io/s/relaxed-meninsky-c5jmw?fontsize=14
如你所见,finalize() operator 在 subject 第二次 emit 时被正确调用,但是:
为什么不调用 tap 运算符的完整处理程序?
不知何故,我对这个运算符的理解只有 80% 的满意度。
相关的不是那个:
我阅读并观看了许多有关 switchMap 的资源,包括:
- 这个(很棒的)ngconf 来源:https://medium.com/@shairez/a-super-ninja-trick-to-learn-rxjss-switchmap-mergemap-concatmap-and-exhaustmap-forever-88e178a75f1b
- 官方 rxjs 文档:https://rxjs-dev.firebaseapp.com/api/operators/switchMap
其中 none 清楚地说明了内部可观察对象是取消订阅还是取消订阅并关闭(或者至少我不明白:))
我看了switchMap算子源码,没有提到takeXXX算子,没有那个他怎么完成内部算子?
tl;dr
- 你确认switchMap在切换时完成了inner observable吗?
- 为什么点击运算符没有按预期工作?
- 如果 switchMap 有效地完成内部 observable,他如何在不使用内部 takeXXX 运算符的情况下做到这一点?
我认为您混淆了 unsubscribe()
和 complete()
之间的区别。对于像 Subject
这样的热门可观察对象,您可以通过几种方式 "stop" 它。从 'top->down' 和 complete()
就像你在你的例子中所做的那样,或者从 'bottom->up' 和 unsubscribe()
.
switchMap()
完全按照它说的去做,它从主要可观察对象切换到次要(或 'inner')可观察对象。这就是为什么当你 complete()
外部 observable 时,它对内部 observable 没有影响 - 链已被切换。要影响链(而不是仅仅影响作为源可观察对象的主题),您需要获得对订阅者的引用,然后调用该订阅者的 unsubscribe()
方法。
为了看到这个,我分叉了你的 CodeSandbox 并制作了这个 new one
正如您将在该 CodeSandbox 中看到的那样,我添加了更多行来显示正在发生的事情:
- 注意链中 switchMap 正上方的新
tap()
- 这将显示在使用 switchMap 运算符将链切换到不同的 Observable 之前直接从Subject()
发生的事情。 - 链的订阅现在正在变量
sub
中捕获,稍后可以取消订阅以从下到上影响链。 - 请注意,10 秒后的
s.complete()
现在反映在主题中,还要注意它根本不影响链。 - 现在请注意,新的
sub.unsubscribe()
在 15 秒后确实会杀死链条。 - 取消注释
newT()
方法中的take(5)
以查看如果上面的源实际完成(自上而下),确实会调用 tap 的 complete 方法。
finalize()
捕捉到发生取消订阅的事实(自下而上),请注意,它发生在 switchMap()
向上自动取消订阅和调用 s.next()
时主题源,以及在订阅上调用 unsubscribe()
时,这再次导致自下而上的终止。在任何情况下,您的 complete()
都不会在原始观察者中调用,因为该链从未真正完成。如果需要,您可以使用 take(10)
运算符完成链,看看它是如何工作的。
希望这有助于稍微消除混乱。 :)