Use case for .PublishLast() (previously Prune)

In my opinion, I have a pretty good "feel" for RX functions - I use many of them or can imagine how other can be useful - but I can't find a place for the .Prune function. I know that this is a Multicast to AsyncSubject, but how this can be useful in a real scenario?

Edit: Richard says WebRequest is a good candidate for Prune(). I still don't see how. Let's take an example - I want to transform incoming uri's to images:

 public static IObservable<BitmapImage> ToImage(this IObservable<string> source) { var streams = from wc in source.Select(WebRequest.Create) from s in Observable .FromAsyncPattern<WebResponse>(wc.BeginGetResponse, wc.EndGetResponse)() .Catch(Observable.Empty<WebResponse>()) select s.GetResponseStream(); return streams .ObserveOnDispatcher() .Select(x => { var bmp = new BitmapImage(); bmp.SetSource(x); return bmp; }); } 

I don't see it necessary to append .Prune to .FromAsyncPattern, because when you're calling FromAsyncPattern() (which is hot) you subscribe "instantly".

1

3 Answers

As it was confirmed on the RX Forum Prune is just a covenience operator.

If your observable has a single value and you're publishing it, can replace Publish\Connect with a single call to .Prune()

So from my experience, the most common scenario for Prune is:

  • You have a cold observable that produces side-effects and emits only one value
  • You have more than one subscriber to that observable, so you want to make it hot (because of side-effects)

Another, pointed out in the forum, is when you need to cache a particular value on a hot observable(usually first). Then you use FromEvent(...).Take(1).Prune() and anybody who subscribes to this will get the same value guaranteed. This one is not just "convenience", but pretty much the only easy way to achieve the result.

Pretty useful, after all!

The most common scenario is when the source observable is hot and can complete before you subscribe to it. The AsyncSubject captures the last value and re-emits it for any future subscribers.

Edit

I'd have to check, but I believe FromAsyncPattern uses an AsyncSubject internally, so is actually already "Pruned".

However, assuming you were working with some other hot source that did not, the use of Prune comes entirely down to the lifetime of the IObservable before it is subscribed to. If you subscribe to it instantly, there is no need for Prune. If the IObservable will exist for a while before being subscribed to, however, it may have already completed.

This is my understanding, as someone who has ported Rx but never used Prune. Maybe you should ask the same question on the Rx forums? You've got a chance of it being answered by someone on the Rx team.

3

I've also found a neat use for it when I've got multiple UI components that need to listen to a task (e.g. callback) and by default, Subscribe() on a cold observable will kick off that task several times which is typically not what you want when sharing state across UI components.

I know Richard mentioned a lot of these points but I figured this is such a perfect candidate for single-run Tasks, to add this example in too.

var oTask = Observable.FromAsync(() => Task.Factory.StartNew(() => { Thread.Sleep(1000); Console.WriteLine("Executed Task"); })); //Setup the IConnectedObservable var oTask2 = oTask.PublishLast(); //Subscribe - nothing happens oTask2.Subscribe(x => { Console.WriteLine("Called from Task 1"); }); oTask2.Subscribe(x => { Console.WriteLine("Called from Task 2"); }); //The one and only time the Task is run oTask2.Connect(); //Subscribe after the task is already complete - we want the results Thread.Sleep(5000); oTask2.Subscribe(x => { Console.WriteLine("Called from Task 3"); }); 
1

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

You Might Also Like