doe
doe

Reputation: 455

RxJS subscription management - avoid excess subscriptions

How can I avoid excess subscriptions?

Is there a function that can be used for making sure any active subscriptions are unsubscribed?

clickDown(e) {
  this.mouseMoveSubscription = fromEvent(this.elementRef.nativeElement, 'mousemove')
    .subscribe((e: MouseEvent) => {
      console.log(e);                                          
    });
}

Upvotes: 0

Views: 139

Answers (4)

Andrew Hill
Andrew Hill

Reputation: 2253

Assuming you're not using async pipes, then the currently accepted pattern is to use either takeUntil or takeWhile to manage your subscriptions onDestroy.

For example:

import { Component, OnDestroy, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { takeWhile } from 'rxjs/operators';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
})
export class AppComponent implements OnInit, OnDestroy {
  unsubscribed = false; // <-- When the component loads, subscriptions are all active.

  constructor(private router: Router) { }

  ngOnInit(): void {
    this.router.events
      .pipe(takeWhile(() => !this.unsubscribed)) // <-- Maintain this subscription while the component is not destroyed.
      .subscribe(() => {});
  }

  ngOnDestroy(): void {
    this.unsubscribed = true; // <-- When the component is destroyed, unsubscribe all subscriptions bound to this.unsubscribed.
  }
}

Upvotes: 2

Martin Choraine
Martin Choraine

Reputation: 2431

Another alternative could be to not subscribe observable manually.

Add subscribe() everywhere can be weary but that's because it's a bad practices

You could use async pipe provided by Angular.
This pipe will subscribe your datas and unsubscribe it when component will be destroyed.

In component do not subscribe

clickDown(e) {
  this.mouseMove$ = fromEvent(this.elementRef.nativeElement, 'mousemove');
}

In template use async

<div *ngIf="mouseMove$ | async as mouseMove">{{mouseMove}}</div>

Upvotes: 1

Eliran Eliassy
Eliran Eliassy

Reputation: 1600

An even better approach will be to just use async pipes inside your components, Why?

  1. They have auto unsubscribe support
  2. They run the markForCheck() function for the change detection, so you can easily move your components to onPush strategy

Upvotes: 0

Maihan Nijat
Maihan Nijat

Reputation: 9354

Unsubscribe from previous and subscribe again if successful:

clickDown(e) {
    if(this.mouseMoveSubscription) this.mouseMoveSubscription.unsubscribe();
    this.mouseMoveSubscription = fromEvent(this.elementRef.nativeElement, 'mousemove')
        .subscribe((e: MouseEvent) => {
            console.log(e);
        });
}

Also, unsubscribe when component destroys:

ngOnDestroy(): void {
    if(this.mouseMoveSubscription) this.mouseMoveSubscription.unsubscribe();
}

Upvotes: 1

Related Questions