I want to subscribe on an IObservable<T>
and unsubscribe (dipose) the subscription right after receiving the first element of type T
, i.e. I only want to call the action on the very first element I get after subscribing.
This is the approach I came up with:
public static class Extensions
{
public static void SubscribeOnce<T>(this IObservable<T> observable, Action<T> action)
{
IDisposable subscription = null;
subscription = observable.Subscribe(t =>
{
action(t);
subscription.Dispose();
});
}
}
Example usage:
public class Program
{
public static void Main()
{
var subject = new Subject<int>();
subject.OnNext(0);
subject.OnNext(1);
subject.SubscribeOnce(i => Console.WriteLine(i));
subject.OnNext(2);
subject.OnNext(3);
Console.ReadLine();
}
}
It works as expected and only prints 2
. Is there anything wrong with this or anything else to consider? Is there a cleaner way using the extension methos that come with RX out of the box maybe?
complete() after it has emitted all of it's values. There's no need to unsubscribe. It completes on it's own, which means it unsubscribes all subscribers automatically. This is also the reason why you don't often notice any memory leaks.
In such scenarios we can use RxJS take(1) operator which is great because it automatically unsubscribes after the first execution.
If you want to call an Observable only one time, it means you are not going to wait for a stream from it. So using toPromise() instead of subscribe() would be enough in your case as toPromise() doesn't need unsubscription.
In Angular applications, it's always recommended to unsubscribe the observables to gain benefits like: Avoids Memory Leaks. Aborting HTTP requests to avoid unwanted calls.
var source = new Subject();
source
.Take(1)
.Subscribe(Console.WriteLine);
source.OnNext(5);
source.OnNext(6);
source.OnError(new Exception("oops!"));
source.OnNext(7);
source.OnNext(8);
// Output is "5". Subscription is auto-disposed. Error is ignored.
Take
automatically disposes of the subscription after the nth
element yields. :)
As far as other things to consider, for your custom observable, you should note that you may also want to pass OnError and OnCompleted notifications to your observer, which Take also handles for you.
The built-in operators have other benefits as well, such as better Dispose
handling.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With