Reputation: 181
What is the best strategy to unsubscribe multiple observable in angular? Just to be clear I use this approach when the application is not big and do not need solutions such as ngrx that in this case would be an overengineering.
Currently I use a subscription instance to add all subscriptions and after that when the component was destroyed i call the unsubscribe method. But also I have seen alternatives using the takeUntil from rxjs.
export class MyComponent implements OnInit, OnDestroy {
$firstObservable: Observable<number> = timer(0, 1000);
$secondObservable: Observable<number> = timer(0, 1000);
private _subscriptions = new Subscription();
constructor() { }
ngOnDestroy(): void {
this._subscriptions .unsubscribe();
}
ngOnInit(): void {
this._subscriptions .add(
this.$firstObservable.subscribe(console.log));
this._subscriptions .add(
this.$secondObservable.subscribe(console.log));
}
}
What would be the best solution?
Upvotes: 16
Views: 11979
Reputation: 8558
I suggest you to use takeUntil()
pipeable operator: https://www.learnrxjs.io/operators/filtering/takeuntil.html
This way, you create a Subject
which is to emit value on ngOnDestroy
and unsubscribe multiple subscriptions all at once
unsubscribeSignal: Subject<void> = new Subject();
firstObservable$: Observable<number> = timer(0, 1000);
secondObservable$: Observable<number> = timer(0, 1000);
ngOnInit() {
this.firstObservable$
.pipe(
takeUntil(this.unsubscribeSignal),
)
.subscribe();
this.secondObservable$
.pipe(
takeUntil(this.unsubscribeSignal),
)
.subscribe();
}
ngOnDestroy(){
this.unsubscribeSignal.next();
// Don't forget to unsubscribe from the subject itself
this.unsubscribeSignal.unsubscribe();
}
Upvotes: 10
Reputation: 24462
A simple way is to store the subscription
object and on ngDestroy
call unsubscribe method.
export class MyComponent implements OnInit, OnDestroy {
$firstObservable: Observable<number> = timer(0, 1000);
$secondObservable: Observable<number> = timer(0, 1000);
private _subscriptions: Subscription[] = [];
constructor() { }
ngOnInit(): void {
this._subscriptions.push(
this.$firstObservable.subscribe(console.log)
);
this._subscriptions.push(
this.$secondObservable.subscribe(console.log)
);
}
ngOnDestroy(): void {
this._subscriptions.forEach(sub => sub.unsubscribe()); // 🧙♂️🧙♂️
}
}
Upvotes: 4
Reputation: 2957
Subscribe
class has an add
method that adds multiple subscriptions into one and then it can be unsubscribed
at once.
subscription1 = observable.subscribe(
// next, err, complete etc
);
subscription2 = observable.subscribe(
// next, err, complete etc
);
adding multiple subscriptions
subscription1.add(subscription2);
unsubscribing all subscriptions at once.
subscription1.unsubscribe();
Upvotes: 6
Reputation:
I'm very disappointed that people don't even mention the async
pipe.
It's very powerful, allowing you to both stop worrying about subscriptions and using on push detection strategy.
To use it, simply remove the subscriptions from your TS, and assign the values to your variables which will be typed as observables.
Just look at the code reduction and simplessness (don't know if it's a word, but kinda don't care)
export class MyComponent {
firstObservable$: Observable<number> = timer(0, 1000);
secondObservable$: Observable<number> = timer(0, 1000);
combination$ = combineLatest(this.firstObservable$, this.secondObservable$)
.pipe(tap(() => console.log()));
}
In your HTML
<ng-container *ngIf="combination$ | async">
Observables are being observed.
</ng-container>
(Even though it's not suited to your question example, you can already see how it's way cleaner & simpler)
And best part, you don't have to worry about memory leaks anymore. Angular takes care of all the subscriptions, leaving you to only care about your code (which is what a good framework is supposed to do).
Upvotes: 7