如何从 ReactiveCommand 捕获异常?

How to catch exception from ReactiveCommand?

我知道如何处理由 ReactiveCommand<T> 调用的异步任务抛出的异常,但是如何处理在任务返回之前抛出的异常?

在下面的示例中,ThrowAndHandle命令在执行时会从异步任务中抛出异常,并且会处理该异常。命令 ThrowButFailToHandle 表明我不能使用 ThrownExceptions 来处理未发生 "in" 任务但在创建任务之前发生的异常。这样的异常如何处理?

public class ViewModel
{
    public IReactiveCommand ThrowAndHandle { get; private set; }
    public IReactiveCommand ThrowButFailToHandle { get; private set; }

    public ViewModel()
    {
        ThrowAndHandle = ReactiveCommand.CreateAsyncTask(_ => ThrowFromTask());
        ThrowAndHandle.ThrownExceptions.Subscribe(HandleException);

        ThrowButFailToHandle = ReactiveCommand.CreateAsyncTask(_ => ThrowBeforeTaskIsReturned());
        ThrowButFailToHandle.ThrownExceptions.Subscribe(ThisMethodWillNotBeCalled);
    }

    private Task ThrowFromTask()
    {
        return Task.Run(() => 
        {
            throw new Exception("This exception will appear in IReactiveCommand.ThrownExceptions");
        });
    }

    private Task ThrowBeforeTaskIsReturned()
    {
        throw new Exception("How can I handle this exception?");
    }

    private void HandleException(Exception ex)
    {
        // This method is called when ThrownFromTask() is called
    }

    private void ThisMethodWillNotBeCalled(Exception ex)
    {   
    }
}

假设您的命令直接绑定到 UI,简短的回答是您不能。

异常将传播到 ExecuteAsync observable 的 onError 处理程序,根据 Execute:

的实现忽略它
    public void Execute(object parameter)
    {
        ExecuteAsync(parameter).Catch(Observable.Empty<T>()).Subscribe();
    }

现在如果你非常需要捕获这个异常,你当然可以:

  • 将 ReactiveCommand 包装到 ICommand 中,在出错时具有不同的 Execute 行为
  • 将传递给 CreateAsyncCommand 的 lambda 包装到 return 异常时的失败任务结果
  • issue/PR 在 reactiveui 上将这些异常也传播到 ThrownExceptions