Do I need to unsubscribe from an Angular Observable? [duplicate]
Asked Answered
C

3

5

It's surprisingly hard to get a straight answer on if and when you should unsubscribe from an Angular Observable.

I have the following scenario:

this.subscription = this.service.makeHTTPCall(stuff).subscribe(x => {
//do something
});

There are a few solutions I see:

  1. Don't store the subscription as a variable, does this mean I don't have to unsubscribe?

    this.service.makeHTTPCall(stuff).subscribe(x => {
    //do something
    });
    
  2. Store the subscription as a variable and unsubscribe in ngOnDestroy

    ngOnDestroy() {
    if (this.subscription) { this.subscription.unsubscribe(); }
    }
    
  3. Do nothing, Angular sorts all of the unsubscribe stuff out for you

I know there are third party libraries like ng-take-until-destroy, but assuming we don't have any third party libraries which is the advised method for unsubscribing?

Cogwheel answered 24/11, 2021 at 8:52 Comment(1)
Have a look to the new takeUntilDestroyed from Angular angular.dev/api/core/rxjs-interop/takeUntilDestroyedCent
B
3

You don't need to unsubscribe manually HTTP Observable and Router observable. Other than these two, any subject, or observable you create you have manually unsubscribe using one way you already mentioned, another way can be using async operator.. The async operator automatically unsubscribes for you, also another way you can use takeUntil operator

From https://mcmap.net/q/45852/-angular-rxjs-when-should-i-unsubscribe-from-subscription

TLDR:

For this question there are (2) kinds of Observables - finite value and infinite value.

http Observables produce finite (1) values and something like a DOM event listener Observables produce infinite values.

If you manually call subscribe (not using async pipe), then unsubscribe from infinite Observables.

Don't worry about finite ones, RxJs will take care of them.

Bohemianism answered 24/11, 2021 at 9:2 Comment(0)
R
8

You don't need to unsubscribe manually HTTP Observable and Router observable. For all others subscribers the best practice is to create a subject onDestroy$ and then take all the subscribers until onDestroy$ is active using the rxjs pipe takeUntil(). In the ngOnDestroy than you emit true in the onDestroy$ subject and unsubscribe from it. All the others subscribers will stop together. Angular do not sorts all of the unsubscribe stuff out for you, you should do it yourself. It can provide to many hard debuggable bugs to leave gost subscribers after component destroy. Below is the example code:

onDestroy$: Subject<boolean> = new Subject();

ngOnInit() {
 this.service.someSubscriber.pipe(takeUntil(this.onDestroy$)).subscribe(() => 
{ //do stuff 
})
this.service.someSubscriber2.pipe(takeUntil(this.onDestroy$)).subscribe(() => 
{ //do stuff 
})
this.service.someSubscriber3.pipe(takeUntil(this.onDestroy$)).subscribe(() => 
{ //do stuff 
})
}

ngOnDestroy() {
  this.onDestroy$.next(true);
  this.onDestroy$.unsubscribe();
}

In html template the async pipe trigger the unsubscribe automatically, so when you use it you can not bother about it.

Revest answered 24/11, 2021 at 9:16 Comment(0)
B
3

You don't need to unsubscribe manually HTTP Observable and Router observable. Other than these two, any subject, or observable you create you have manually unsubscribe using one way you already mentioned, another way can be using async operator.. The async operator automatically unsubscribes for you, also another way you can use takeUntil operator

From https://mcmap.net/q/45852/-angular-rxjs-when-should-i-unsubscribe-from-subscription

TLDR:

For this question there are (2) kinds of Observables - finite value and infinite value.

http Observables produce finite (1) values and something like a DOM event listener Observables produce infinite values.

If you manually call subscribe (not using async pipe), then unsubscribe from infinite Observables.

Don't worry about finite ones, RxJs will take care of them.

Bohemianism answered 24/11, 2021 at 9:2 Comment(0)
W
3

For some cold observables, you don't need to manually unsubscribe because they will emit once and then complete immediately after. The http service is an example of such an observable.

That being said, if if you don't know whether an observable will emit once and complete immediately, then you should always do proper cleanup.

Personally, I prefer using the take(1) operator, which will take the first response and then unsubscribe itself:

someObs.pipe(take(1)).subscribe(...)
Wastebasket answered 24/11, 2021 at 9:16 Comment(3)
Hello. Is there any difference doing it this way vs setting the subscribe to a Subscription type variable and then unsubscribing it in OnDestroy? This was seems a lot easier and less code.Twelfth
@Twelfth doing like this prevents more than one update happening. Instead of a continious update stream it behaves more like a Promise.Yean
@Twelfth it's essentially the same thing. Take unsubscribes and completes the observable after the nth value is seen. Check out the source code for take: github.com/ReactiveX/rxjs/blob/master/packages/rxjs/src/…Wastebasket

© 2022 - 2024 — McMap. All rights reserved.