为什么订阅函数中的代码会多次执行

时间:2019-01-24 14:23:22

标签: angular rxjs

我已经为我的应用程序创建了一个通知服务,如下所示:

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});
  }

这是我如何使用此服务的示例:

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

由于我有一个在我所有组件之间共享的组件(即标头),因此我在ngOnInit函数中订阅了通知服务主题:

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

我第一次运行该应用程序时,当我调用某些notificationService函数时,subscribe函数中的代码就会执行一次,但是之后,subscribe函数中的代码将执行多次。

我该如何解决?

2 个答案:

答案 0 :(得分:2)

每次创建标头组件的实例时,它都会为您的Notification Service创建另一个订阅。当标题组件被销毁时,它必须清理其订阅。如果不是,那么只要可观察对象发出新值,subscribe块就会继续执行。

通常,订阅服务的任何组件都应包含ngOnDestroy生命周期方法,该方法将清除其已进行的所有订阅。

要自动退订,可以将componentDestroyed主题与rxjs takeUntil运算符一起使用。在ngOnDestroy中,您在componentDestroyed上发射一个值,以完成预订:

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.

答案 1 :(得分:0)

您正在从notifsuccesserrorinfo等其他方法中调用warning方法。notif方法正在对您的next调用Subject,最终通过在其上调用Subject方法将新值推送到您已作为Observable公开的asObservable()

请确保未在应用程序中的其他任何地方调用successerrorinfowarning等。如果多次调用这些方法,则subscribe方法也将被调用多次。