Why does Rx buffer continuously perform method when buffer contains no items?

后端 未结 2 1468
忘了有多久
忘了有多久 2021-01-05 01:59

I have a Rx Observable that acts as a buffer. Right now it performs the method in Subscribe either when it gets 10 items, or after 100 milliseconds, whichever comes first.

相关标签:
2条回答
  • 2021-01-05 02:33

    Perhaps try it like this:

    public MyBufferClass(IMyServer server, IScheduler scheduler)
    {
        this.serverRequests = new Subject<KeyValuePair<int, Action<MyData>>>();
    
        this.serverRequests
            .GroupByUntil(x => 1, x => Observable.Timer(TimeSpan.FromMilliseconds(1000)))
            .SelectMany(x => x.ToArray())
            .Subscribe(buffer => GetMultipleItemsFromServer(buffer));
    }  
    

    That doesn't give you empty results.

    And the answer to your question regarding .Buffer(...) - that's the way it has been designed. Nothing more complicated than that.

    0 讨论(0)
  • 2021-01-05 02:51

    In situations like this an elegant solution can be to use the Where operator straight after the Buffer to filter out any empty results. Something like this:

                stream
                .Buffer (...)
                .Where (x => x.Any())
                .Subscribe (x => {...}, ex => {...});
    

    As to why Buffer acts like this, I suppose it's better to surface an empty collection and allow the consumer to choose what to do with it, than to swallow it and deny that opportunity.

    On a separate note, I wouldn't have your server call within the subscribe block. I think it's a better idea to have any asynchronous operations as a part of the Rx stream composition itself, and to restrict the Subscribe action to any lightweight operations that deal with the final result, i.e. updating the UI, logging success/failure etc. Something like this:

    (from request in serverRequests
                .Buffer (TimeSpan.FromMinutes (1))
                .Where (x => x.Any())
    from response in Observable.Start(server.GetMultipleItems(...))
    select response)
    .Subscribe (x => {}, ex => {});
    

    Advantages to this include:

    -Being able to use further Rx operators on your server call, such as Timeout(), Retry(), Catch(), etc.

    -Being able to handle any pipeline errors within the Subscribe() overload

    -Independent scheduling of the pipeline and the Subscribe action with SubscribeOn()/ObserveOn().

    0 讨论(0)
提交回复
热议问题