0

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 ?

3
  • How do you share the header component between your other components? Commented Jan 24, 2019 at 14:50
  • @AlexK All my components have this in line in their html code <app-header></app-header> so the header will always appear. Commented Jan 24, 2019 at 15:12
  • Why don't you put the header in the app.component.html, above your router outlet so it is only defined one time for all of the components? Commented Jan 24, 2019 at 17:53

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

Comments

0

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.

2 Comments

I get it now, the purpose of this code is to call the notification service method multiple times, I'm still learning about this Observable thing but I can't figure out how to solve this, I only want the code inside the subscribe function to get called once.
Please refer to the second paragraph on my answer. You'll have to remove additional calls to the methods if you want the subscribe to get called only once. Or else share a working sample stackblitz replicating this issue so that I could have a look into it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.