我从 Ollie Riches' 博客文章Trying to be more functional with Rx中读到了以下内容,并且成为了与作者一样的想法:为什么不是 OnCompleted 通过呢?有人能说出这里发生了什么吗?也许是一件令人尴尬的简单事情?
为方便起见,代码有点修改和复制(如果在这里翻录他的代码是不可接受的,我向Ollie道歉):
public static class RxExtensions
{
public static IObservable<T> Suspendable<T>(this IObservable<T> stream, IObservable<bool> suspend, bool initialState = false)
{
return Observable.Create<T>(o =>
{
var disposable = suspend.StartWith(initialState)
.DistinctUntilChanged()
.Select(s => s ? Observable.Empty<T>() : stream)
.Switch()
.Subscribe(o);
return disposable;
});
}
}
var testScheduler = new TestScheduler();
var generatorCount = 10;
//If the limit will be hardcoded to something less than generatorCount, an exception will be
//thrown and the exception object will be set. Why it doesn't happen to completed in the following?
var generator = Observable.Generate(1,
x => x <= generatorCount,
x => x + 1,
x => { if(x != 11) { Console.WriteLine(x); return x; } else { throw new ArgumentException(); } },
x => TimeSpan.FromSeconds(1),
testScheduler);
Exception exception = null;
var completed = false;
generator.Suspendable(new Subject<bool>()).Subscribe(_ => { }, e => exception = e, () => completed = true);
testScheduler.AdvanceBy(TimeSpan.FromMilliseconds(1001000).Ticks);
Console.WriteLine(exception);
Console.WriteLine(completed);
为了记录,我正在考虑尝试生成一个可以暂停和停止的流,区别是暂停的流累积事件,暂停只是跳过它们。它开始看起来比我预期的要多一些,特别是如果一个人想要限制或者拯救战略&#34;停顿了一下。哦,好吧......
&lt; edit:有趣的是,我刚注意到RxJS implementation of Pausable。
答案 0 :(得分:1)
您的观察者订阅了suspend
流和source
流。在两个流完成之前,该组合流将不会完成。基本上,您的source
流已完成,但Suspendable
正在等待查看是否会有更多暂停/取消暂停信号。如果他们这样做,它将重新订阅源流。
要在源流完成时完成可循环流,但可能会破坏方法的目的。有些事情基本上必须保持订阅源流并在源完成时结束暂停的流。你可以这样做:
var shared = stream.Publish();
var pausable = suspend
.StartWith(initialState)
.TakeUntil(shared.LastOrDefaultAsync())
.DistinctUntilChanged()
.Select(p => p ? shared : Observable.Empty<T>())
.Switch();
var disposable = new CompositeDisposable(pausable.Subscribe(o), shared.Connect());
return disposable;
答案 1 :(得分:0)
已完成未发送,因为您的订阅位于Observable.Empty()而不是_generator的后代
所以,我使用 CombineLatest
public static IObservable<T> Suspendable<T>(
this IObservable<T> source,
IObservable<bool> pauser,
bool initialState = false)
{
return
source.CombineLatest(pauser.StartWith(initialState),
(value, paused) => new {value, paused})
.Where(_=>!_.paused)
.Select(_=>_.value);
}