【问题标题】:RX.Net : Use Retry but log any ExceptionRX.Net:使用重试但记录任何异常
【发布时间】:2017-06-07 22:17:57
【问题描述】:

我是 RX 新手,一直在研究错误处理和重试的使用;我有以下内容(是的,我知道这不是一个“真正的”单元测试,但它给了我摆弄的地方!!)并且想知道我如何去保持重试但能够记录任何异常?

    [Test]
    public void Test()
    {
        var scheduler = new TestScheduler();

        var source = scheduler.CreateHotObservable(
            new Recorded<Notification<long>>(10000000, Notification.CreateOnNext(0L)),
            new Recorded<Notification<long>>(20000000, Notification.CreateOnNext(1L)),
            new Recorded<Notification<long>>(30000000, Notification.CreateOnNext(2L)),
            new Recorded<Notification<long>>(30000001, Notification.CreateOnError<long>(new Exception("Fail"))),
            new Recorded<Notification<long>>(40000000, Notification.CreateOnNext(3L)),
            new Recorded<Notification<long>>(40000000, Notification.CreateOnCompleted<long>())
        );

        source.Retry().Subscribe(
            l => Console.WriteLine($"OnNext {l}"), 
            exception => Console.WriteLine(exception.ToString()), // Would be logging this in production
            () => Console.WriteLine("OnCompleted"));

       scheduler.Start(
            () => source,
            0,
            TimeSpan.FromSeconds(1).Ticks,
            TimeSpan.FromSeconds(5).Ticks);
    }

这会导致...

OnNext 0
OnNext 1
OnNext 2
OnNext 3
OnCompleted

...除了我想记录发生在 2 和 3 之间的异常之外,这正是我想要发生的事情。

有没有办法让订阅者看到 OnError 中的异常(并记录它),然后重新订阅,以便它看到 3?

谢谢!

【问题讨论】:

    标签: system.reactive rx.net


    【解决方案1】:

    您可以通过以下方式实现:

    source
        .Do(_ => { }, exception => Console.WriteLine(exception.ToString()), () => {})
        .Retry()
        .Subscribe(
            l => Console.WriteLine($"OnNext {l}"),
            //      exception => Console.WriteLine(exception.ToString()), // Would be logging this in production
            () => Console.WriteLine("OnCompleted")
        );
    

    只是为了澄清这里发生了什么:OnError 是一个终止信号。如果错误到达订阅,那将终止流的其余部分。 .Retry 终止订阅,吞下OnError,然后重新订阅,将两个订阅融合在一起。例如看这个:

    source
        .StartWith(-1)
        .Retry()
        .Subscribe(
            l => Console.WriteLine($"OnNext {l}"),
            () => Console.WriteLine("OnCompleted")
        );
    

    您的输出将是

    OnNext -1
    OnNext 0
    OnNext 1
    OnNext 2
    OnNext -1
    OnNext 3
    OnCompleted
    

    OnNext -1 出现两次,因为它会在您订阅时出现(RetryOnError 之后出现。

    坦率地说,您的测试 observable 是一个糟糕的测试。它打破了“Rx 合同”,即通知遵循以下模式:

    OnNext* (OnCompleted | OnError)? 
    

    即,0 个或多个OnNext 通知,后跟可选的OnError 或可选的OnCompleted。任何类型的通知都不应跟在OnErrorOnCompleted 之后。

    【讨论】:

    • 关于bad test;试图把一个简单的例子放在一起但失败的结果!! :-( 感谢您的澄清,我还没有完全理解 Retry 的功能。
    • 我的应用程序中实际拥有的是从 FromEventPattern 驱动的热可观察对象。我收到一个包含 byte[] 的事件,然后我解密 byte[],建立消息类型并相应地反序列化;在 Observer.OnNext 我根据该消息执行操作。如果我在这些操作(解密/序列化等)中有任何问题,我不希望发生流终止。我只想记录失败并继续处理。这可能吗?
    • “我不想发生的是流终止”应该是“我不想发生的是订阅终止”
    • 是的,.Retry 就是这么做的。它终止并重新订阅,但以对下游订阅者透明的方式。
    • 你可以登录,只需要在重试之前完成。
    猜你喜欢
    • 2020-08-17
    • 1970-01-01
    • 2014-08-15
    • 1970-01-01
    • 1970-01-01
    • 2017-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多