【问题标题】:Angular2, unsubsribe from event in ngOnDestroy [duplicate]Angular2,取消订阅 ngOnDestroy 中的事件 [重复]
【发布时间】:2016-04-27 20:50:11
【问题描述】:

在我的应用程序中,我有一些组件通过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中的按钮时,会多次执行ReceiverComponent的事件回调函数。

为了避免这种情况,我在ngOnDestroy 中从myEvent 取消订阅ReceiverComponent

ngOnDestroy() {
  this.eventService.myEvent.unsubscribe();
}

但这会导致以下异常

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

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

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

【问题讨论】:

    标签: angular eventemitter


    【解决方案1】:

    您从.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();
      }
    }
    

    另见

    【讨论】:

    • 这正是我所做的,但是当我将视图更改为 pageB 并返回 pageA 时,这会导致“错误:无法订阅已处理的主题”
    • 对我来说看起来不一样。我错过了什么吗?在您的问题中,您使用 this.eventService.myEvent.unsubscribe();subscription.unsubscribe();
    • 哦,对不起,我的错,我没有注意到差异。现在可以了,非常感谢!
    • 为什么需要这个? this.subscription 是一个类变量,应该和类的其余部分一起自动销毁?
    • @TGH 好问题。当eventService.myEvent 仍然引用引用ReceiverComponent.count 的闭包时,我不知道ReceiverComponent 是否可以被GC。
    【解决方案2】:

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

    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 是共享的 observable,即 hot observable。这是您可能感兴趣的链接:https://github.com/Reactive-Extensions/RxJS/blob/master/doc/gettingstarted/creating.md

    希望对你有帮助 蒂埃里

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-11
      • 1970-01-01
      • 2018-05-27
      • 2021-07-22
      • 1970-01-01
      • 2018-08-31
      • 1970-01-01
      • 2021-10-06
      相关资源
      最近更新 更多