Вот (чрезмерно) упрощенная версия того, что я пытаюсь продемонстрировать:
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 reactiveCommandA.ExecuteAsync().Catch(Observable.Never<Unit>());
, хотя я думаю, что это приведет к тому, что reactiveCommandC никогда не завершится, поэтому он никогда не сможет выполниться снова.Используя тот же подход с методом
.Catch()
, но возвращая логическое значение в зависимости от того, успешно я это сделал или нет (например,.Catch(Observable.Return(false))
. Все равно придется проверять, можем ли мы продолжить между каждым операторомawait
.
Здесь можно сделать что-нибудь похлеще? Спасибо.