Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/drupal/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何干净地重新连接到ReplaySubject,同时避免过去的回忆录副作用?_Javascript_Rxjs_Observable_Subject - Fatal编程技术网

Javascript 如何干净地重新连接到ReplaySubject,同时避免过去的回忆录副作用?

Javascript 如何干净地重新连接到ReplaySubject,同时避免过去的回忆录副作用?,javascript,rxjs,observable,subject,Javascript,Rxjs,Observable,Subject,我将状态保存在一个回放状态的最后一个副本的ReplaySubject中。从该状态派生出其他replaysubject,以保存……嗯,派生状态。每个重播主题只需保留其上次计算的状态/派生的状态。(我们不使用行为子对象,因为它们总是给出一个值,但我们只需要从父观察值派生出一个值。)如果我们已经生成派生状态,则始终需要将该值重播给新订户。 我有一个自定义的可观察操作符,它以我想要的方式完成这项工作,但它感觉不那么干净。我觉得应该有一个有效的方法来实现这一点,RxJ的运营商自己 我尝试过两种最明显的方法

我将状态保存在一个回放状态的最后一个副本的
ReplaySubject
中。从该状态派生出其他
replaysubject
,以保存……嗯,派生状态。每个重播主题只需保留其上次计算的状态/派生的状态。(我们不使用
行为子对象
,因为它们总是给出一个值,但我们只需要从父观察值派生出一个值。)如果我们已经生成派生状态,则始终需要将该值重播给新订户。

我有一个自定义的可观察操作符,它以我想要的方式完成这项工作,但它感觉不那么干净。我觉得应该有一个有效的方法来实现这一点,RxJ的运营商自己

我尝试过两种最明显的方法,但每种方法都有一些小问题。问题涉及取消订阅和重新订阅。 打开下面的小提琴,打开控制台,然后单击run。我将描述每个输出的问题

引用计数的问题ed ReplaySubject

=== RefCounted Observable ===


Work
Subscription 1: 1
Work
Subscription 1: 2
Work
Subscription 1: 3
Unsubscribe
Resubscribe
Subscription 2: 3
Work
Subscription 2: 6
Work
Subscription 2: 7
Work
Subscription 2: 8
=== Hot Observable ===
Work
Subscription 1: 1
Work
Subscription 1: 2
Work
Subscription 1: 3
Unsubscribe
Work
Work
Work
Resubscribe
Subscription 2: 6
Work
Subscription 2: 7
Work
Subscription 2: 8
这很好,中间函数在没有订阅的情况下不做任何工作。但是,一旦我们重新订阅。我们可以看到Subscription 2会重播取消订阅之前的最后一个状态,然后根据
base$
状态中的当前值播放派生状态。这并不理想

连接的问题
ed ReplaySubject

=== RefCounted Observable ===


Work
Subscription 1: 1
Work
Subscription 1: 2
Work
Subscription 1: 3
Unsubscribe
Resubscribe
Subscription 2: 3
Work
Subscription 2: 6
Work
Subscription 2: 7
Work
Subscription 2: 8
=== Hot Observable ===
Work
Subscription 1: 1
Work
Subscription 1: 2
Work
Subscription 1: 3
Unsubscribe
Work
Work
Work
Resubscribe
Subscription 2: 6
Work
Subscription 2: 7
Work
Subscription 2: 8
这一个没有与
refCount
ed observable相同的问题,没有不必要的取消订阅前最后一个状态的重播。然而,由于可观察对象现在很热门,因此折衷的办法是,每当新值进入
base$
状态时,我们总是进行工作,即使该值未被任何订阅使用

最后,我们有一个自定义操作符:

=== Custom Observable ===
Work
Subscription 1: 1
Work
Subscription 1: 2
Work
Subscription 1: 3
Unsubscribe
Resubscribe
Work
Subscription 2: 6
Work
Subscription 2: 7
Work
Subscription 2: 8
啊,两全其美。它不仅不会不必要地重播取消订阅之前的最后一个值,而且在没有订阅时也不会不必要地执行任何工作。 这是通过手动创建
RefCount
ReplaySubject
的组合来实现的。我们跟踪每个订户,当它达到0时,我们刷新重播值。代码在这里(当然也在小提琴中):

因此,这个定制的可观察对象已经起作用了。但是,只有RxJS操作符才能做到这一点吗?请记住,可能不止有几个这样的主题联系在一起。在这个例子中,我只使用了一个到
base$
的链接,用我在最基本的层面上尝试过的两种普通方法来说明这个问题。
基本上,如果您只能使用RxJS操作符,并获得与上面的
===自定义可观察====
的输出相匹配的输出。这就是我要找的。谢谢

您应该能够将
多播
与主题工厂而不是主题一起使用。比照

这一过载正好服务于您的用例。每次
多播
操作符返回的可观察对象完成并重新连接到时,它都会使用提供的工厂创建一个新主题。虽然没有很好的文档记录,但它基本上是从RxJSV4复制了一个现有的API


如果我误解了或不起作用,请告诉我,

这里没有误解,它完全按照预期工作!非常感谢你。我尝试过混混
多播
,但我真的不知道它是如何工作的;我不知道是什么使它与
publish
特别不同。我甚至没有意识到你可以通过一个工厂!这很有帮助。因此,与其试图让
ReplaySubject
在取消订阅时删除它的状态,我们只需在订阅时扔掉它,如果我们重新订阅,就可以得到一个新的。美丽的!谢谢:)
sourceObservable.publish().refCount()
是编写
sourceObservable.multicast(new Rx.Subject()).refCount()的一种简写方式。而
sourceObservable.share()
是编写
sourceObservable.publish().refCount()的一种简写方式