角度4 + ngOnDestroy()在服务-摧毁观察

在一个有角度的应用程序中,我们使用 ngOnDestroy()生命周期钩子作为组件/指令,并使用这个钩子来取消订阅可观察到的内容。

我想清除/销毁在 @injectable()服务中创建的可观察到的。 我看到一些帖子说 ngOnDestroy()也可以在服务中使用。

但是,这是一个好的实践和唯一的方法吗? 它什么时候会被调用? 有人能澄清一下吗。

121006 次浏览

在服务中创建一个变量

subscriptions: Subscriptions[]=[];

将每个订阅按如下方式推送到数组

this.subscriptions.push(...)

编写一个 dispose()方法

dispose(){
this.subscriptions.forEach(subscription =>subscription.unsubscribe())

在 ngOnDestroy 期间从组件调用此方法

ngOnDestroy(){
this.service.dispose();
}

只是要澄清-你不需要销毁 Observables,但只有订阅了他们。

似乎其他人已经指出,您现在也可以将 ngOnDestroy与服务一起使用。链接: https://angular.io/api/core/OnDestroy

OnDestroy 生命周期钩子在提供程序中可用。 根据文件:

当指令、管道或服务被破坏时调用的生命周期钩子。

这是 例子:

@Injectable()
class Service implements OnDestroy {
ngOnDestroy() {
console.log('Service destroy')
}
}


@Component({
selector: 'foo',
template: `foo`,
providers: [Service]
})
export class Foo implements OnDestroy {
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被销毁时,它可以被销毁。

对于属于 root 注入器的提供程序,这将在应用程序销毁时发生,这有助于避免多个引导程序(即在测试中)的内存泄漏。

当来自父注入器的提供者在子组件中订阅时,它不会在组件销毁时被销毁,这是组件在组件 ngOnDestroy中取消订阅的责任(另一个答案解释)。

我更喜欢这种由可管操作符启用的 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 何时退订

使用标记时要小心

为了使我的应用程序尽可能模块化,我经常使用提供者令牌来为组件提供服务。看起来这些不得到他们的 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被调用了。

不确定这是不是一个错误,但是非常出乎意料。

在服务中创建一个变量:

private subscriptions$ = new Subscription();

将每个订阅添加到构造函数(或 ngOnInit 生命周期挂钩)中的可观察项

ngOnInit() {
this.subscriptions.add(...)
this.subscriptions.add(...)
}

销毁时从组件调用此方法以取消对所有订阅和子订阅的订阅。

ngOnDestroy(){
this.subsriptions$.unsubscribe();
}

我建议使用. tube (take (1)) . ordering ()。