在一个角度应用程序中,我们有一个组件/指令的ngOnDestroy()
生命周期钩子,我们使用这个钩子来取消订阅observables。
我想清除在@injectable()
服务中创建的/ destory observable。
我看到一些帖子说ngOnDestroy()
也可以在服务中使用。
但是,这是一个很好的做法,也是唯一的方法吗?什么时候会被调用? 有人请澄清。
答案 0 :(得分:55)
OnDestroy生命周期钩子。 根据文件:
销毁指令,管道或服务时调用的生命周期钩子。
这是example:
@Injectable()
class Service implements OnDestroy {
ngOnDestroy() {
console.log('Service destroy')
}
}
@Component({
selector: 'foo',
template: `foo`,
providers: [Service]
})
export class Foo {
constructor(service: Service) {}
ngOnDestroy() {
console.log('foo destroy')
}
}
@Component({
selector: 'my-app',
template: `<foo *ngIf="isFoo"></foo>`,
})
export class App {
isFoo = true;
constructor() {
setTimeout(() => {
this.isFoo = false;
}, 1000)
}
}
请注意,在上面的代码中,Service
是一个属于Foo
组件的实例,因此在Foo
被销毁时可以将其销毁。
对于属于根注入器的提供程序,这将在应用程序销毁时发生,这有助于避免多个引导的内存泄漏,即在测试中。
当来自父注入器的提供者在子组件中订阅时,它不会在组件销毁时被销毁,这是组件在组件ngOnDestroy
中取消订阅的责任(另一个答案解释)
答案 1 :(得分:18)
在您的服务中创建变量
subscriptions: Subscriptions[]=[];
将每个订阅推送到数组
this.subscriptions.push(...)
编写dispose()
方法
dispose(){
this.subscriptions.forEach(subscription =>subscription.unsubscribe())
在ngOnDestroy
期间从您的组件调用此方法ngOnDestroy(){
this.service.dispose();
}
答案 2 :(得分:5)
只是为了澄清 - 您不需要销毁Observables
,只需要销毁订阅。
似乎其他人已经指出您现在也可以将ngOnDestroy
用于服务。链接:https://angular.io/api/core/OnDestroy
答案 3 :(得分:3)
我更喜欢由可插值运算符启用的takeUntil(onDestroy$)
模式。我喜欢这种模式更简洁,更简洁,并且清楚地传达了在执行OnDestroy
生命周期挂钩时取消订阅的意图。
此模式适用于服务以及订阅已注入可观察对象的组件。下面的框架代码应为您提供足够的详细信息,以将模式集成到您自己的服务中。假设您要导入名为InjectedService
...
import { InjectedService } from 'where/it/lives';
import { Injectable, OnDestroy } from '@angular/core';
import { Observable } from 'rxjs/Rx';
import { takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs/Subject';
@Injectable()
export class MyService implements OnDestroy {
private onDestroy$ = new Subject<boolean>();
constructor(
private injectedService: InjectedService
) {
// Subscribe to service, and automatically unsubscribe upon `ngOnDestroy`
this.injectedService.observableThing().pipe(
takeUntil(this.onDestroy$)
).subscribe(latestTask => {
if (latestTask) {
this.initializeDraftAllocations();
}
});
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
此处何时/如何退订的主题广泛涉及:Angular/RxJs When should I unsubscribe from `Subscription`
答案 4 :(得分:1)
在尝试使我的应用程序尽可能模块化时,我经常使用提供者令牌为组件提供服务。看来这些方法并没有获得称为:-(
的ngOnDestroy
方法
例如
export const PAYMENTPANEL_SERVICE = new InjectionToken<PaymentPanelService>('PAYMENTPANEL_SERVICE');
在组件中具有提供者部分:
{
provide: PAYMENTPANEL_SERVICE,
useExisting: ShopPaymentPanelService
}
处置组件时,我的ShopPaymentPanelService
没有调用其ngOnDestroy
方法。我只是很难找到答案!
一种解决方法是与useExisting
一起提供服务。
[
ShopPaymentPanelService,
{
provide: PAYMENTPANEL_SERVICE,
useExisting: ShopPaymentPanelService
}
]
执行此操作时,ngOnDispose
的调用符合预期。
不确定这是不是bug,但是非常意外。
答案 5 :(得分:0)
在您的服务中创建一个变量:
private subscriptions$ = new Subscription();
在构造函数(或 ngOnInit 生命周期钩子)中将每个订阅添加到 observable
ngOnInit() {
this.subscriptions.add(...)
this.subscriptions.add(...)
}
在销毁时从您的组件调用此方法以取消订阅所有订阅和子订阅。
ngOnDestroy(){
this.subsriptions$.unsubscribe();
}