Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between .unsubscribe to .take(1)

I wonder, if there is any difference in performance between using .take(1) and .unsubscribe when unsubscribe is used right after the subscription:

var observable = Rx.Observable.interval(100); 

First:

var subscription = observable.subscribe(function(value) {    console.log(value); }).unsubscribe(); 

Second:

var subscription = observable.take(1).subscribe(function(value) {     console.log(value); }); 

Any ideas of it makes any different regard the performance?

like image 277
TheUnreal Avatar asked Nov 12 '16 12:11

TheUnreal


People also ask

Do I need to unsubscribe from router events?

You should always unsubscribe when using the events observables from the Router in components (there is one exception tough, namely if you use it in the root component) as the subscription is still alive, even if the component was destroyed by Angular.

Does First automatically unsubscribe?

The RxJS first() operator waits until the first value is emitted from an observable and then automatically unsubscribes, so there is no need to explicitly unsubscribe from the subscription.

Do I need to unsubscribe from Take 1?

These are called “finite subscriptions”. If you subscribe with a “take(1)”, as another example, it is finite and doesn't need to be unsubscribed. This is easy enough to test out if you are unsure of it being finite or infinite. For example, you could console.

What is the best place to unsubscribe observables and detach event handlers?

The best place to make the notifier to emit so the observable$ is canceled is in the ngOnDestroy hook.


1 Answers

Each serves a different purpose so it's hard to compare them.

In general if you take this source:

const source = range(1,3); 

... and consume it with subscribe() followed immediately by unsubscribe():

source.subscribe(   console.log,   undefined,    () => console.log('complete') ).unsubscribe(); 

... then all values from source are going to be emitted even though we called unsubscribe() right after subscribing. This is because the code is still strictly sequential (synchronous) and the source is a cold Observable.

1 2 3 complete 

Btw, try adding delay(0) operator to make source.pipe(delay(0)).subscribe(...).unsubscribe(). This makes emitting values asynchronous using an actual setTimeout() call and for this reason unsubscribe() is called before any next handlers and is discarded immediately.

In other words unsubscribe() let's you stop receiving values anytime. Even when the source hasn't emitted any value (we never receive any complete notification).

Using take() operator limits the chain to only emit a specific number of values.

source.pipe(   take(1), ) .subscribe(   console.log,   undefined,   () => console.log('complete') ); 

This just emits a single value and completes:

1 complete 

Even if you add .unsubscribe() the result would be the same.

See live demo: https://stackblitz.com/edit/rxjs-tbu5kb

So take() is an operator while unsubscribe() is a method on a Subscription object. These two things are often interchangeable but they never fully substitute each other.

Jan 2019: Updated for RxJS 6

like image 170
martin Avatar answered Oct 09 '22 09:10

martin