Renaud is Not Bill Gates
Renaud is Not Bill Gates

Reputation: 2084

Why code inside subscribe function executes multiple times

I have created a notification service for my application as following :

export class NotificationService {
  private subject = new Subject<Notification>();

  constructor() {}

  getNotification(): Observable<any>{
    return this.subject.asObservable();
  }

  success(title: string, message: string){
    this.notif(NotificationType.SUCCESS, title, message);
  }

  error(title: string, message: string){
    this.notif(NotificationType.ERROR, title, message);
  }

  technicalError(title:string, message: string){
    this.notif(NotificationType.TECHNICAL_ERROR, title, message);
  }

  info(title: string, message: string){
    this.notif(NotificationType.INFO, title, message);
  }

  warning(title: string, message: string){
    this.notif(NotificationType.WARNING, title, message);
  }

  notif(type: NotificationType, title: string, message: string){
    this.subject.next(<Notification>{ type: type, title: title, message: message});
  }

And this is an example on how I use this service:

this.notificationService.success("Suppression", "L'enregistrement a été supprimée !");

And since I have a component which is shared between all my components which is the header, I have a subscribe for the notification service subject in it's ngOnInit function:

this.notificationService.getNotification().subscribe((notification: Notification) => {
      this.notification.create(NotificationType[notification.type], notification.title, notification.message);
    });

For the first time I run the application the code inside subscribe function is executed once when I call some notificationService function, but after that the code inside the subscribe function executes multiple times.

How can I solve this ?

Upvotes: 0

Views: 1383

Answers (2)

alexhughesking
alexhughesking

Reputation: 2007

Each time an instance of your Header Component is created, it creates another subscription to your Notification Service. When the Header Component is destroyed, it must clean up its subscriptions. If not, the subscribe block will continue to execute whenever the observable emits a new value.

In general, any component which subscribes to a service should contain an ngOnDestroy lifecycle method which cleans up any subscriptions it has made.

To unsubscribe automatically, you can use a componentDestroyed Subject along with the rxjs takeUntil operator. In ngOnDestroy, you emit a value on componentDestroyed which completes the subscription:

export class HeaderComponent implements OnInit, OnDestroy {
  private componentDestroyed = new Subject<any>();

  constructor(private notificationService: NotificationService) { }

  ngOnInit() {
    this.notificationService.getNotification()
      .pipe(takeUntil(this.componentDestroyed))
      .subscribe(notification => {
        // ...
      });
  }

  ngOnDestroy() {
    this.componentDestroyed.next();
  }
}

Here's a StackBlitz example.

Upvotes: 2

SiddAjmera
SiddAjmera

Reputation: 39482

You're calling the notif method from other methods like success, error, info, warning etc. The notif method is calling next on your Subject which eventually is pushing a new value to the Subject that you have exposed as an Observable by calling the asObservable() method on it.

Make sure that you're not calling the success, error, info, warning etc. anywhere else in your application. If these methods are called more than once, the subscribe method will also get called more than once.

Upvotes: 0

Related Questions