任务可观察错误处理



我有以下方法,它负责调用我的服务类并将结果传递给另一个方法,以便将结果保存在我的数据库中:

public IObservable<bool> SyncSessions()
{
    var subject = new ReplaySubject<bool>();
    try
    {
        var query = new ByFilterQuery { SearchPeriodStartTime = DateTime.Now };
        var sessions = _sessionService.GetSessions(query).Result;
        var saved = SaveSessions(sessions);
        subject.OnNext(saved);
        subject.OnCompleted();
    }
    catch (Exception ex)
    {
        subject.OnError(ex);
    }
    return subject;
 }

_如果服务器返回500或类似的值,sessionService.GetSessions将抛出HttpRequestException。我有一个单元测试,它模拟了这种行为,并希望测试我的方法优雅地处理错误。

有没有更好的方法以Rx方式传播错误?我试着做:

_sessionService.GetSessions(query).ToObservable().Select(SaveSessions);

但是这抛出了我的错误,而不是将其传递给调用方法中的错误处理操作。我还计划将此方法与其他几种方法合并,并在组合庄园中处理错误。

编辑:以下是我订阅可观察的方式

Exception error = null;
_sessionManager
    .SyncSessions()
    .Subscribe(null, e => error = e);
Assert.That(error, Is.Not.Null.After(500));

我将null传递到第一个参数中,因为在这个测试

的上下文中我并不真正关心它

首先,对于您发布的原始代码,我建议使用AsyncSubject而不是ReplaySubject。可以将其视为针对单个结果案例进行优化。

现在谈谈你的问题。。。

每当可观察源生成异常时,该异常都会通过OnError处理程序传播。如果在订阅observable时没有提供OnError处理程序,则会引发异常。

你发布的小代码:

_sessionService.GetSessions(query).ToObservable().Select(SaveSessions);

还不够。如果不发布显示您如何订阅observable的代码,我只能猜测您没有提供OnError处理程序。

根据OP的测试代码进行编辑

您的模拟服务是返回抛出异常的Task,还是模拟服务只是抛出异常?除非使用async/await,否则一个本应返回Task但在创建Task时抛出异常的函数将立即引发异常,而不是返回失败的Task。ToObservable甚至从未被调用,因为GetSessions抛出。如果您更改模拟服务以返回失败的Task,那么您的测试可能会正常工作。

如果您想捕获立即的异常和失败的任务,那么您可以使用Defer来推迟方法的执行,直到观察者订阅为止。除了失败的任务外,它还将收集任何立即抛出的异常:

return Observable
    .Defer(() => _sessionService.GetSessions(query))
    .Select(SaveSessions);

最新更新