Reactive approach to simple imperative task

后端 未结 3 1304
予麋鹿
予麋鹿 2021-01-05 07:54

Application requirements:

  • subscribe to two event streams A and B
  • for each A event there should be corresponding B event some time later
  • the a
3条回答
  •  情话喂你
    2021-01-05 08:06

    This should work. The types differ, I didn't want to guess your probably abstract datatypes. You can apply them pretty easily (function parameters, key comparison and Select statements)

    Idea is that for every emited value from a, we take the first value emited either by b.Where(keys match) or timeout (presented by Observable.Timer) and make our Select based on this information.

    I assumed that in timeout cases you also want on OnNext notification with some error provisioning mechanism.

    private IObservable MonitorAB(IObservable a, IObservable b,
                                          TimeSpan threshold)
    {
        return Observable.Create((obs) =>
        {
            a = a.Publish().RefCount();
            b = b.Publish().RefCount();
            return a.Subscribe(i =>
            {
                Observable.Merge(Observable.Timer(threshold).Select(_ => $"Timeout for A{i}"),
                                 b.Where(j => j == i).Select(_ => $"Got matching B for A{i}"))
                          .Take(1)
                          .Subscribe(obs.OnNext);
            });
        });
    }
    

    I tested it like this.

    private void Test()
    {
        var a = Observable.Interval(TimeSpan.FromSeconds(2)).Take(5);
        var b = Observable.Interval(TimeSpan.FromSeconds(5)).Take(5);
        MonitorAB( a, b, TimeSpan.FromSeconds(13)).Subscribe(Console.WriteLine);
    }
    

    EDIT: to test the out of order case, you can flip the B stream e.g.

    var b = Observable.Interval(TimeSpan.FromSeconds(2)).Select(i  => 4 - i).Take(5);
    

提交回复
热议问题