提问者:小点点

Angular Service已被销毁,但为什么订阅仍在接收来自可观察的订阅?


使用Angular,我有一个组件中提供的服务。该服务有一个可观察对象,并且该组件订阅了这个可观察对象。我原以为我不需要取消订阅/可观察对象,因为该服务应该与组件一起销毁,因此也是可观察对象。然而,快速测试显示可观察对象是活动的。

在我的视线之外发生了什么?可观察对象是否在服务之外运行?或者当提供它的组件被销毁时,服务实际上并没有被销毁?


共3个答案

匿名用户

在你的场景中使用totoit。您需要创建/初始化一个主题,该主题将在组件销毁时完成。

private unsubscribe: Subject<void> = new Subject<void>();


this.testService.testObservable().pipe(takeUntil(this.unsubscribe))
.subscribe(data => console.log(data));

组件销毁完成订阅

使用主题和取值,您可以在ngOnDestory一次取消订阅多个可观察对象。

public ngOnDestroy(): void {
    this.unsubscribe.next();
    this.unsubscribe.complete();
  }

匿名用户

如果你订阅了一个未完成的可观察对象,你就会有内存泄漏。即使服务是由组件提供的,你也在服务中创建了一个可观察对象并将其返回给组件。现在可观察对象被组件引用,不再与创建它的服务有任何关系。当组件被销毁时,它将被标记为垃圾回收机制,但仍然存在于内存中,直到垃圾收集器清理资源。你仍然需要取消订阅未完成的可观察对象。

有几个选择

  1. 使用异步管道,因为它将为您管理订阅并取消订阅
  2. 保留对订阅的引用并在ngOnDestroy上调用取消订阅
  3. 对主语使用带直到,使主语发出ngOnDestroy。

带至的好处是,您可以使用它来管理多个订阅,而不必单独跟踪每个订阅。

1:异步管

data$ = this.testService.testObservable();

并认为

<ng-container *ngIf="data$ | async as data">
  {{ data | json }}
</ng-container>

2:退订

this.subscription = this.testService.testObservable().subscribe(data => console.log(data));

ngOnDestroy() {
  if (this.subscription) {
    this.subscription.unsubscribe();
  }
}

3:带至

finalise = new Subject<void>();

this.subscription = this.testService.testObservable().pipe(takeUntil(this.finalise)).subscribe(data => console.log(data));

ngOnDestroy() {
  this.finalise.next();
  this.finalise.complete();
}

匿名用户

当我们返回或使用间隔时,可观察对象将不断接收流,直到我们停止它。为最佳实践,您应该使用间隔可观察对象和RxJS运算符来自动销毁订阅。

// RxJS v6+
import { interval, timer } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

//emit value every 1s
const source = interval(1000);
//after 5 seconds, emit value
const timer$ = timer(5000);
//when timer emits after 5s, complete source
const example = source.pipe(takeUntil(timer$));
//output: 0,1,2,3
const subscribe = example.subscribe(val => console.log(val));

[注意]如果您使用的是setInterval,则需要使用ngOnDestroy显式取消订阅