Renato Santos
Renato Santos

Reputation: 181

How to unsubscribe multiple observables in angular component?

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

Answers (4)

Harun Yilmaz
Harun Yilmaz

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

Muhammed Albarmavi
Muhammed Albarmavi

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

Aamer Shahzad
Aamer Shahzad

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

user4676340
user4676340

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

Related Questions