Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to use doOnTerminate vs doOnUnsubscribe?

I need to be notified when something subscribes to my observable. I also need to be notified that the observable has either errored or completed. So I thought I should use doOnSubscribe:

register an action to take when an observer subscribes to an Observable

and doOnTerminate:

register an action to take when an Observable completes, either successfully or with an error

Then I saw doOnUnsubscribe:

register an action to take when an observer unsubscribes from an Observable

and thought the symmetry of doOnSubscribe/doOnUnsubscribe would be better.

So, will doOnTerminate always be called before doOnUnsubscribe? If I just want to know that things are "done", does it really matter which I choose?

like image 517
tir38 Avatar asked Nov 03 '16 17:11

tir38


1 Answers

The way unsubscribe happens in your reactive flow will determine which one from doOnUnsubscribe or doOnTerminate you can use. The following can be the cases:

Observable completion/error triggers unsubscribe
In such a scenario both doOnTerminate and doOnUnsubscribe will be called with doOnTerminate being called first.

The below example will print both terminated and unsubscribed.

Subscription subscribe = Observable.empty() // source terminates immediately
    .subscribeOn(Schedulers.newThread()) 
    .doOnTerminate(() -> System.out.println("terminated"))
    .doOnUnsubscribe(() -> System.out.println("unsubscribed"))
    .subscribe();

TimeUnit.SECONDS.sleep(1);
subscribe.unsubscribe(); // by this time already unsubscribe would have happened

Programatic call to unsubscribe before Observable completes
In such a scenario only doOnUnsubscribe will be called. The chance of this happening is more prevalent when you have a source which runs infinitely or a source which is hot like an observable for user clicks.

The below example will only print unsubscribed.

Subscription subscribe = Observable.never() // source never terminates
    .subscribeOn(Schedulers.newThread())
    .doOnTerminate(() -> System.out.println("terminated"))
    .doOnUnsubscribe(() -> System.out.println("unsubscribed"))
    .subscribe();

TimeUnit.SECONDS.sleep(1);
subscribe.unsubscribe(); // this will trigger unsubscribe
like image 88
Praveer Gupta Avatar answered Sep 30 '22 14:09

Praveer Gupta