这是我要演示的(过度)简化版本:
var reactiveCommandA = ReactiveCommand.CreateAsyncTask(_ => CanPossiblyThrowAsync());
reactiveCommandA.ThrownExceptions
.Subscribe(ex => UserError.Throw("Oh no A", ex));
var reactiveCommandB = ReactiveCommand.CreateAsyncTask(_ => CanAlsoPossiblyThrowAsync());
reactiveCommandB.ThrownExceptions
.Subscribe(ex => UserError.Throw("Oh no B", ex));
var reactiveCommandC = ReactiveCommand.CreateAsyncTask
(
async _ =>
{
await reactiveCommandA.ExecuteAsync(); // <= Could throw here
await reactiveCommandB.ExecuteAsync();
DoSomethingElse();
}
);
reactiveCommandC.ThrownExceptions
.Subscribe(ex => UserError.Throw("Oh no C", ex));
假设我的后台实现是 reactiveCommandA
可能会抛出异常。没关系,因为我已经订阅了 .ThrownExceptions
理论上会通知用户并重试/失败/中止(为简洁起见,此处未显示)。所以它不会冒泡到调度员。
所以当 reactiveCommandA
时这很棒是自己执行的。但是,我有 reactiveCommandC
执行 reactiveCommandA
和 reactiveCommandB
.我也订阅了它的.ThrownExceptions
.我遇到的问题是,如果我执行 reactiveCommandC
和 reactiveCommandA
实现在其中抛出,它也会导致 reactiveCommandC
去炸掉。然后我两次通知用户相同的根错误,因为 reactiveCommandA
做它的.ThrownExceptions
事情,然后 reactiveCommandC
做它的.ThrownExceptions
那么对于这种情况有标准的方法吗?最好是有点优雅的东西,因为我发现现有代码相当干净,我不想把事情搞得一团糟或引入意大利面条。
我想到的事情:
用
try/catch
包围“await...”行阻止并吞咽异常并退出。如果我必须经常这样做,那就太丑了。使用
await reactiveCommandA.ExecuteAsync().Catch(Observable.Never<Unit>());
尽管我认为这会导致 reactiveCommandC 永远无法完成,因此它永远无法再次执行。使用与
.Catch()
相同的方法方法,但根据我是否成功通过返回一个 bool 值(例如.Catch(Observable.Return(false))
。仍然需要检查我们是否可以在每个await
语句之间继续。
这里有什么更巧妙的事情吗?谢谢。
最佳答案
嗯,这是 ReactiveCommand 设计的一个方面,有点糟糕(披露:我可以说它很糟糕,我写了它!)这是修复它的懒惰方法:
Observable.Merge(rxCmdA.ThrownExceptions, rxCmdB.ThrownExceptions, rxCmdC.ThrownExceptions)
.Throttle(TimeSpan.FromMilliseconds(250), RxApp.MainThreadScheduler)
.Subscribe(ex => UserError.Throw("Oh no C", ex));
在未来我肯定想修复一些这样的双重抛出问题,以及一些关于 RxCmd 设计的其他问题。
关于c# - 执行劣质 ReactiveCommand 时,ReactiveUI 处理异常的方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26219105/