基于下游条件的RX过滤器

时间:2018-01-15 09:40:24

标签: f# reactive-programming system.reactive

我正在尝试根据下游条件过滤掉更多上游项目。 mapProcess本质上启动一个Process(脚本或exe)。该过程可能需要一些时间才能完成,我想在完成之前忽略任何进一步的上游项目。 createProcess还返回一个Obdable of StdOut。我们切换到createProcess创建的IObservable并将arg映射到StdOut。

实施例

let mapProcess obs =
  obs
  |> Observable.map (fun arg -> createProcess arg)
  |> Observable.switch

我做了什么:这有效,但对这里的可变性并不完全满意。

let mapProcess obs =
  let mutable processNotRunning = true
  obs
  |> Observable.filter (fun _ -> processNotRunning)
  |> Observable.map (fun arg -> processNotRunning <- false
                                createProcess arg)  
  |> Observable.switch
  |> Observable.iter (fun _ -> processNotRunning <- true)
  |> Observable.finallyDo (fun _ -> processNotRunning <- true)

我认为我可能需要的是某种“switchIfSeen”Observable函数,只有在当前订阅的observable已生成项目或已完成时才会切换。我可能只是通过组合一些现有的RX功能而错过了一种更简单的方法吗?

1 个答案:

答案 0 :(得分:2)

  

[...]仅在当前订阅的observable产生了一个时才切换   项目或已完成

忽略值的一种方法是将热观察值转换为冷可观察量 - 因此无论谁在聆听,它都可以推出项目。然后,你只在需要的时候听。

  var map = argn.Select(CreateProcess).Publish().RefCount();

        map.SelectMany(o => o) //flatmap
           .Take(1)
           .Repeat()
           .Subscribe(d => Console.WriteLine($"Did task which took {d * 100}msecs" ));

测试:

CreateProcess只是一个定时器,它会产生x100毫秒的固定延迟。)

    private static void Main(string[] args)
    {
        var argn = Observable.Interval(TimeSpan.FromMilliseconds(100)).Publish().RefCount();
        argn.Subscribe(Console.WriteLine);

        var map = argn.Select(CreateProcess).Publish().RefCount();

        map.SelectMany(o => o)
           .Take(1)
           .Repeat()
           .Subscribe(d => Console.WriteLine($"Did task which took {d * 100}msecs" ));

        Console.ReadKey();
    }

    static IObservable<long> CreateProcess(long i) => Observable.Timer(TimeSpan.FromMilliseconds(i * 100)).Select(_ => i);

输出:

0
Did task which took 0msecs
1
2
Did task which took 100msecs
3
4
5
Did task which took 300msecs
6
7
8
9
10
11
Did task which took 600msecs