Angular2,取消订阅 ngOnDestroy 中的事件

Angular2, unsubsribe from event in ngOnDestroy

在我的应用程序中,我有一些组件通过 EventService.

进行通信
@Injectable()
export class EventService {
  public myEvent: EventEmitter<any> = new EventEmitter();
  constructor() {}
}

此服务被注入到 EmitterComponent 中,当单击按钮时会发出事件

@Component({
  selector: 'emitter',
  template: `<button (click)="onClick()">Click me</button>`,
})
export class EmitterComponent {
  constructor(private eventService:EventService) {}
  onClick() {
    this.eventService.myEvent.emit();
  }
}

并且在订阅事件的 ReceiverComponent 中,对于接收到的每个事件递增一个计数器

@Component({
  selector: 'receiver',
  template: `Count: {{count}}`,
})
export class ReceiverComponent {
  public count = 0;
  constructor(private eventService:EventService) {
    this.eventService.myEvent.subscribe(() => this.count++;);
  }
}

该应用程序有多个视图(在此示例中只有两个):PageAPageBEmitterComponentReceiverComponentPageA 中。每次我去PageB然后回到PageA,都会创建一个新的ReceiverComponent,当我点击EmitterComponent中的按钮时,[=17]的事件回调函数=]被执行了几次。

为了避免这种情况,我在 ngOnDestroy

中从 myEvent 退订了 ReceiverComponent
ngOnDestroy() {
  this.eventService.myEvent.unsubscribe();
}

但这会导致以下异常

EXCEPTION: Error during instantiation of ReceiverComponent!.
ORIGINAL EXCEPTION: Error: Cannot subscribe to a disposed Subject

我怎样才能避免这种情况?如何正确退订?

为了更好地理解,我创建了这个 plunker,您可以在控制台中看到错误和一些注释。

您从 .subscribe() 获得订阅。使用其 unsubscribe() 方法取消订阅。

@Component({
  selector: 'receiver',
  template: `Count: {{count}}`,
})
export class ReceiverComponent {
  public count = 0;
  private subscription;
  constructor(private eventService:EventService) {
    this.subscription = this.eventService.myEvent.subscribe(() => this.count++;);
  }
  ngOnDestroy() {
    this.subscription.unsubscribe();
  }
}

另见

我认为您应该取消订阅,如下所述:

export class ReceiverComponent {
  public count = 0;
  private id;

  constructor(private eventService:EventService) {
    this.id = Date.now();
    console.log("ReceiverComponent constructor " + this.id);
    this.subscription = this.eventService.myEvent.subscribe(() => {
      console.log("count " + this.count + " (id ReceiverComponent instance: " + this.id + ")");
      this.count++;
    });
  }

  ngOnDestroy() {
    console.log("onDestroy of ReceiverComponent " + this.id)
    //this cause "Cannot subscribe to a disposed Subject."
    //this.eventService.myEvent.unsubscribe();
    this.subscription.unsubscribe();
  }
}

事实上,EventEmitters 是共享的可观察对象,即热可观察对象。这是您可能感兴趣的 link:https://github.com/Reactive-Extensions/RxJS/blob/master/doc/gettingstarted/creating.md.

希望对你有帮助, 蒂埃里