这是我试图演示的(过度)简化版本:
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));
Run Code Online (Sandbox Code Playgroud)
因此,假设我的后台实现reactiveCommandA可能会引发异常。没关系,因为我已经订阅.ThrownExceptions并且理论上会通知用户并重试/失败/中止(为简洁起见,此处未显示)。所以它不会冒泡给调度员。
所以当reactiveCommandA它自己执行时就很棒了。但是,我有reactiveCommandCwhich 执行reactiveCommandA和reactiveCommandB。我也订阅了它的.ThrownExceptions。我遇到的问题是,如果我执行reactiveCommandC并reactiveCommandA在其中抛出实现,它也会导致reactiveCommandC爆炸。然后我会两次通知用户相同的根错误,因为先做reactiveCommandA它的.ThrownExceptions事情,然后reactiveCommandC再做它的.ThrownExceptions事情。
那么对于这种情况有标准的方法吗?最好是一些优雅的东西,因为我发现现有的代码相当干净,我不想让事情变得混乱或引入意大利面条。
我想到的事情:
用块包围“await...”行try/catch并吞咽异常并退出。如果我必须做很多事情,那就太丑了。
尽管await reactiveCommandA.ExecuteAsync().Catch(Observable.Never<Unit>());我认为这会导致reactiveCommandC永远无法完成,所以它永远无法再次执行。
使用与该.Catch()方法相同的方法,但根据我是否成功通过返回一个布尔值(例如.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));
Run Code Online (Sandbox Code Playgroud)
将来我肯定想修复一些此类双掷问题,以及有关 RxCmd 设计的其他一些问题。
| 归档时间: |
|
| 查看次数: |
2362 次 |
| 最近记录: |