长话短说
对于这个问题,有两种可观察量—— 有限 值和 无限 值。
http
可观察对象产生 有限 (1)的值,而类似 DOM 事件监听器的可观察对象则产生 无限的 值。
如果您手动调用 subscribe
(不使用异步管道),那么 unsubscribe
将从 无限的 Observables 中调用。
不要担心 有限的 ,RxJs 会处理它们。
资料来源:
-
p6
p7
p8
p9
p10
p11
-
p12
p13
p14
p15
p16
p17
-
第18页
第19页
-
p20
-
p21
p22
p23
我在 NGConf 上与 Ward Bell 讨论了这个问题(我甚至向他展示了这个答案,他说这是正确的),但他告诉我 Angular 的文档团队对这个问题有一个尚未发布的解决方案(尽管他们正在努力获得批准)。他还告诉我,我可以用即将发布的官方建议更新我的 SO 答案。
我们今后都应该使用的解决方案是向 private ngUnsubscribe = new Subject<void>();
在其类代码中调用 Observables .subscribe()
的组件添加一个字段
然后我们调用 this.ngUnsubscribe.next(); this.ngUnsubscribe.complete();
我们的 ngOnDestroy()
方法。
秘诀(正如 @metamaker 在每次调用之前 takeUntil(this.ngUnsubscribe)
调用 .subscribe()
,这将保证在组件被销毁时所有订阅都将被清理。
例子:
import { Component, OnDestroy, OnInit } from '@angular/core';
// RxJs 6.x+ import paths
import { filter, startWith, takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs';
import { BookService } from '../books.service';
@Component({
selector: 'app-books',
templateUrl: './books.component.html'
})
export class BooksComponent implements OnDestroy, OnInit {
private ngUnsubscribe = new Subject<void>();
constructor(private booksService: BookService) { }
ngOnInit() {
this.booksService.getBooks()
.pipe(
startWith([]),
filter(books => books.length > 0),
takeUntil(this.ngUnsubscribe)
)
.subscribe(books => console.log(books));
this.booksService.getArchivedBooks()
.pipe(takeUntil(this.ngUnsubscribe))
.subscribe(archivedBooks => console.log(archivedBooks));
}
ngOnDestroy() {
this.ngUnsubscribe.next();
this.ngUnsubscribe.complete();
}
}
注意: 将操作符添加为最后一个非常重要, takeUntil
以防止操作符链中的中间 Observable 发生泄漏。
最近,在 《Adventures in Angular》 ,Ben Lesh 和 Ward Bell 讨论了如何/何时在组件中取消订阅的问题。讨论开始于 1:05:30 左右。
Ward 提到 “现在有一个糟糕的 takeUntil 舞蹈,需要很多机器”, 而 Shai Reznik 提到 “Angular 处理一些订阅,如 http 和路由” .
作为回应,Ben 提到现在正在讨论允许 Observables 挂接到 Angular 组件生命周期事件中,而 Ward 建议使用一个生命周期事件的 Observable,组件可以订阅该 Observable 以此来了解何时完成作为组件内部状态维护的 Observables。
话虽如此,我们现在最需要的是解决方案,所以这里还有一些其他资源。
-
p34
-
p35
-
p36
-
p37
我在 Nicholas 博客的评论中提到,过度使用 takeUntil()
可能表明您的组件试图做太多事情, 应该考虑将 功能 和 演示 | async
功能组件中的 Observable 放入 Input
演示组件中,这意味着任何地方都不需要订阅。 在此处 .