当其他可观察对象为真时,从可观察对象中获取项目

Posted

技术标签:

【中文标题】当其他可观察对象为真时,从可观察对象中获取项目【英文标题】:Take items from observable when other observable is true 【发布时间】:2021-12-28 16:14:03 【问题描述】:

如何根据另一个可观察的 b 的(布尔)值来控制通过可观察的 a 推送哪些项目?

我的意思是,只有当 b 发出的最后一个项目为真时,才会推送 a 中的项目。

可观察序列 b 应该像一个通过过滤器。

【问题讨论】:

【参考方案1】:

好的,我想我至少有一个解决方案 可以通过WithLatestFromWhere 的组合来完成。

在我的真实代码中,我有这个:

视频中可观察到的位置 可观察的布尔值,指示用户是否已开始“搜索”操作(通过在视频播放器中任意拖动拇指)
positionObs
   .WithLatestFrom(isSeekingObs, (pos, isSeeking) => new  pos, isSeeking )
   .Where(x => !x.isSeeking)
   .Select(x => x.pos);

它必须结合两个最近的值并对“信号器”应用过滤器。

无论如何,我想知道是否有更清洁的解决方案。

【讨论】:

使用CombineLatest 如果布尔控制序列切换过于频繁,您可能会得到重复。我认为WithLatestFrom 是您所需要的。 感谢@TheodorZoulias!我已经更新了答案。它就像一个魅力 + 这是我第一次使用该运算符。【参考方案2】:

我更喜欢使用PublishSwitch 的组合。

方法如下:

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_aobservable_a 已发布这一事实并不重要。

以上是关于当其他可观察对象为真时,从可观察对象中获取项目的主要内容,如果未能解决你的问题,请参考以下文章

使用异步管道从可观察对象中读取对象字段

无法从可观察对象中提取数据

我如何从可观察对象创建对象,该对象返回对象数组

如何强制视图刷新而不让它从可观察对象自动触发?

如何将一个观察值与先前的观察值相乘,但仅当某个条件为真时

Angular 4 - 从可观察到的将新项目推送到数组