我有一个延迟加载模块的应用程序。
在一个特定的延迟加载模块中,我有一个父组件,它有router-outlet
。
在该父组件中,我有一个按钮,它基本上使用共享服务(在延迟加载的模块上提供)发出事件。
每个子组件(在router-outlet
中加载)都使用相同的共享服务订阅该事件!
我尝试使用 heroes demo 在以下plunkr中重新创建我的用例。
打开开发工具以查看console
条消息。
Heroes
链接(默认情况下应该选中)。Admin
链接。Emit Test
按钮(右上导航)你会在控制台看到 - 两个组件都收到了Event,即使两个组件都不应该是“活动”!!!
1)这是设计吗?
2)如何知道当前组件是否为活动组件?
根据我的理解,EventEmitter / Subject可以多次订阅,但是当取消订阅时你不能使用它/订阅它AFAIK。
我的解决方案是:
1)在服务中我结束了下面的事情:
get(){
if (!this.testEvent.closed) {
this.testEvent.complete();
this.testEvent.unsubscribe();
}
this.testEvent= new EventEmitter<void>();
return this.testEvent;
}
}
2)在我订阅活动的每个组件中,我添加了ngDestroy并取消订阅了该活动:
ngOnDestroy() {
this.testEvent.unsubscribe();
}
答案 0 :(得分:1)
您有一项服务,这是一个单身人士。该服务从应用程序的开始到结束都存在。
你有两个组成部分。这些不是单身人士。当它们必须显示在页面上时会被创建,并且当它们不再存在时会被销毁。
并且,在创建组件时,您在单例服务中订阅了一个observable。这是什么意思?这意味着observable需要保持对您的观察者的引用,观察者本身对组件实例具有一个重复引用(this)。如果没有该引用,则在发出事件时,observable将无法调用观察者。因此,即使Angular不再需要您的组件实例,observable仍然会引用它,并在发出事件时调用它。
因此,您需要在不再需要该组件时取消订阅:
private subscription: Subscription;
ngOnInit() {
this.subscription = this.service.getTestEvent().subscribe(...);
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
如果不这样做,你不仅会让观察者一无所获,使应用程序变慢,而且还会出现内存泄漏。
答案 1 :(得分:1)
重点是您永远不会取消订阅该活动。
您点击用户的次数越多,您在控制台中看到的行就越多。
只要您单击订阅该事件,即添加一个将在事件被引发时执行的回调,除非您取消订阅。
在方法ngOnDestroy()
中,您应该在订阅上调用unsubscribe()
方法(这是subscribe()
方法返回的对象)。
换句话说就像这样
subscrition: Subscription;
ngOnInit() {
this.subscription = this.service.getTestEvent().subscribe( (e) => {
console.log('HeroListComponent ==>');
});
.....
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
我希望这会有所帮助。