[英]Rx: How to perform an action on inner observable finish with minimum boilerplate?
為了簡化Rx,我正在編寫一個簡單的應用程序,該應用程序模仿讀取文件並支持取消。
它是這樣的:
當用戶按下“運行”按鈕時,程序
如果用戶按下“取消”按鈕,則文件讀取過程將被取消。
我正在尋找一種使用最少的粘合代碼來實現此目標的方法,同時仍然保持簡單的同步操作序列的外觀,在該序列中可以輕松看到自然的控制流程。
主要問題似乎是當內部可觀察到的(閱讀器)完成時隱藏忙碌指示器,外部可觀察到的是“運行”單擊事件序列。
到目前為止,我提出了程序主要部分的以下兩個版本:
基於訂閱者:
IObservable<byte[]> xs =
runClick
.Do((Action<EventPattern<EventArgs>>)(_ => ShowBusy(true)))
.Do(_ => ShowError(false))
.Select(_ =>
reader
.TakeUntil(cancelClick)
.Publish(ob =>
{
ob.Subscribe(
b => { },
ex =>
{
Console.WriteLine("ERROR: " + ex);
ShowBusy(false);
ShowError(true);
},
() => ShowBusy(false));
return ob;
}))
.Switch();
xs = xs.Catch<byte[], Exception>(e => xs);
並且基於concat:
IObservable<byte[]> xs =
runClick
.Do((Action<EventPattern<EventArgs>>)(_ => ShowBusy(true)))
.Do(_ => ShowError(false))
.Select(_ =>
reader
.TakeUntil(cancelClick)
.DoAfter(() =>
ShowBusy(false)))
.Switch();
xs = xs.Catch<byte[], Exception>(e =>
{
Console.WriteLine("ERROR: " + e);
ShowBusy(false);
ShowError(true);
return xs;
});
使用一種自定義方法DoAfter
public static IObservable<T> DoAfter<T>(this IObservable<T> observable, Action action)
{
IObservable<T> appended = observable.Concat(
Observable.Create<T>(o =>
{
try
{
action();
}
catch (Exception ex)
{
o.OnError(ex);
return Disposable.Empty;
}
o.OnCompleted();
return Disposable.Empty;
}));
return appended;
}
(請參閱此處的整個應用程序代碼)。
兩種實現方式都不能完全滿足我的要求:第一種方法很冗長,第二種方法則迫使我編寫自己的方法來完成一項相當簡單的任務,我希望該任務可以用標准方法涵蓋。 我想念什么嗎?
原來我缺少的是Do
方法的重載 。 我可以使用它代替我的自定義DoAfter
方法,然后代碼看起來不錯。
IObservable<byte[]> xs =
runClick
.Do((Action<EventPattern<EventArgs>>)(_ => ShowBusy(true)))
.Do(_ => ShowError(false))
.Select(_ =>
reader
.TakeUntil(cancelClick)
.Do(
b => { },
ex =>
{
Console.WriteLine("ERROR: " + ex);
ShowBusy(false);
ShowError(true);
},
() => ShowBusy(false)
))
.Switch();
xs = xs.Catch<byte[], Exception>(e => xs);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.