当其他可观察对象为真时,从可观察对象中获取项目
Posted
技术标签:
【中文标题】当其他可观察对象为真时,从可观察对象中获取项目【英文标题】:Take items from observable when other observable is true 【发布时间】:2021-12-28 16:14:03 【问题描述】:如何根据另一个可观察的 b 的(布尔)值来控制通过可观察的 a 推送哪些项目?
我的意思是,只有当 b 发出的最后一个项目为真时,才会推送 a 中的项目。
可观察序列 b 应该像一个通过过滤器。
【问题讨论】:
【参考方案1】:好的,我想我至少有一个解决方案
可以通过WithLatestFrom
和Where
的组合来完成。
在我的真实代码中,我有这个:
视频中可观察到的位置 可观察的布尔值,指示用户是否已开始“搜索”操作(通过在视频播放器中任意拖动拇指)positionObs
.WithLatestFrom(isSeekingObs, (pos, isSeeking) => new pos, isSeeking )
.Where(x => !x.isSeeking)
.Select(x => x.pos);
它必须结合两个最近的值并对“信号器”应用过滤器。
无论如何,我想知道是否有更清洁的解决方案。
【讨论】:
使用CombineLatest
如果布尔控制序列切换过于频繁,您可能会得到重复。我认为WithLatestFrom
是您所需要的。
感谢@TheodorZoulias!我已经更新了答案。它就像一个魅力 + 这是我第一次使用该运算符。【参考方案2】:
我更喜欢使用Publish
和Switch
的组合。
方法如下:
Subject<bool> subject_b = new();
IObservable<bool> observable_b = subject_b.AsObservable();
IObservable<long> observable_a = Observable.Interval(TimeSpan.FromSeconds(1.0));
IObservable<long> observable_c =
observable_a
.Publish(published_a =>
observable_b
.Select(value_b =>
value_b
? published_a
: Observable.Never<long>()))
.Switch();
IDisposable subscription = observable_c.Subscribe(Console.WriteLine);
Thread.Sleep(TimeSpan.FromSeconds(2.5));
subject_b.OnNext(true);
Thread.Sleep(TimeSpan.FromSeconds(3));
subject_b.OnNext(false);
Thread.Sleep(TimeSpan.FromSeconds(4));
subject_b.OnNext(true);
这给了:
2
3
4
9
10
11
12
13
14
...
比起WithLatestFrom
,我更喜欢Publish
/Switch
,因为前者处理的查询种类更多,而后者不处理。
【讨论】:
这种方式虽然您不会收到关于observable_a
序列完成的即时通知,但如果它发生在控制序列(subject_b
)处于false
状态时。我想这在某些情况下可能是可取的。
@TheodorZoulias - 是的,因为Publish
。
您可以查看this fiddle。 A 序列的成功完成永远不会通过 C 序列传播。 A 序列的失败仅在稍后通过 C 序列传播,此时 B 序列发出 true
。取消注释.Concat(Observable.Throw...
行以测试失败案例。
这对我来说似乎是一个错误。它应该停止。
为什么? observable_c
基于observable_b
,而不是observable_a
。 observable_a
已发布这一事实并不重要。以上是关于当其他可观察对象为真时,从可观察对象中获取项目的主要内容,如果未能解决你的问题,请参考以下文章