简体   繁体   English

接收缓存-重播操作员清除

[英]Rx Cache - Replay operator Clear

I am using the following code from here - looks like an issue to me in clearing the " Replay cache " 我在这里使用以下代码-清除“ 重放缓存 ”对我来说似乎是一个问题

https://gist.github.com/leeoades/4115023 https://gist.github.com/leeoades/4115023

If I change the following call and code like this I see that there is bug in Replay ie it is never cleared. 如果我更改下面的调用和类似的代码,我会发现Replay中存在错误,即从未清除。 Can someone please help to rectify this ? 有人可以帮助纠正这一点吗?

private Cache<string> GetCalculator()
    {
        var calculation = Observable.Create<string>(o =>
        {
            _calculationStartedCount++;

            return Observable.Timer(_calculationDuration, _testScheduler)
                             .Select(_ => "Hello World!" + _calculationStartedCount) // suffixed the string with count to test the behaviour of Replay clearing
                             .Subscribe(o);
        });

        return new Cache<string>(calculation);
    }

[Test]
    public void After_Calling_GetResult_Calling_ClearResult_and_GetResult_should_perform_calculation_again()
    {
        // ARRANGE
        var calculator = GetCalculator();

        calculator.GetValue().Subscribe();
        _testScheduler.Start();

        // ACT
        calculator.Clear();

        string result = null;
        calculator.GetValue().Subscribe(r => result = r);
        _testScheduler.Start();

        // ASSERT
        Assert.That(_calculationStartedCount, Is.EqualTo(2));
        Assert.That(result, Is.EqualTo("Hello World!2")); // always returns Hello World!1 and not Hello World!2
        Assert.IsNotNull(result);
    }

The problem is a subtle one. 问题是一个微妙的问题。 The source sequence Timer completes after it emits an event, which in turn calls OnCompleted on the internal ReplaySubject created by Replay . 源序列Timer在发出事件后完成,该事件又对Replay创建的内部ReplaySubject调用OnCompleted When a Subject completes it no longer accepts any new values even if a new Observable shows up. Subject完成后,即使出现新的Observable它也不再接受任何新值。

When you resubscribe to the underlying Observable it executes again, but isn't able to restart the Subject , so your new Observer can only receive the most recent value before the ReplaySubject completed. 重新订阅基础Observable它将再次执行,但无法重新启动Subject ,因此新的Observer只能在ReplaySubject完成之前接收最新值。

The simplest solution would probably just be to never let the source stream complete (untested): 最简单的解决方案可能就是永远不要让源流完成(未经测试):

    public Cache(IObservable<T> source)
    {
        //Not sure why you are wrapping this in an Observable.create
        _source = source.Concat(Observable.Never())
                            .Replay(1, Scheduler.Immediate);
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM