5

我是 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?

谢谢!

4

1 回答 1

7

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

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.

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

OnNext* (OnCompleted | OnError)? 

也就是说,0 个或多个OnNext通知,后跟一个 optionalOnError或 optional OnCompleted。任何类型的通知都不应跟在 anOnErrorOnCompleted.

于 2017-06-06T14:51:20.947 回答