如何取消订阅 @Output 为 Observable

How to unsubscribe @Output as Observable

我对取消订阅 Angular 中的 Output 有疑问。我知道 EventEmitter 会自动清理,但上次我需要使用 Observable 作为我的 Output。我的意思是,我想要 Output 每秒最多发出一次事件。所以我的代码看起来像:

@Output() loadNextEvent: Observable<any>;
loadNextSubject = new Subject();

constructor(private el: ElementRef) {
    this.loadNextEvent = this.loadNextSubject.asObservable()
        .throttleTime(1000); // once per second
    }

emit() {
    this.loadNextSubject.next('new event');
}

好的,它工作得很好 - 我想。唯一的问题是退订。我在 Whosebug 上找到了 ,但我仍然不确定我应该如何正确地做到这一点。就我而言:

@Output() loadNextEvent: Observable<any>;
loadNextSubject = new Subject();

constructor(private el: ElementRef) {
    this.loadNextEvent = this.loadNextSubject.asObservable()
        .takeUntil(this.loadNextSubject) //does it make any sense?
        .throttleTime(1000); // once per second
    }

emit() {
    this.loadNextSubject.next('new event');
}

ngOnDestroy() {
    this.loadNextSubject.complete();
}

问题: 这是 observable Output 的正确取消订阅吗? .takeUntil(this.loadNextSubject) 有什么意义吗?或者,当 Subject 完成时,.asObservable() 可以确保 Observable 已被清理?有人知道我的问题的答案吗?或者,也许有更好的解决方案,然后将 Observable 用作 Output,对我而言?

如果你想使用 takeUntil 通知器 Observable 需要发出 next 通知而不仅仅是完成。所以正确的做法是这样的:

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

此外,在这种情况下您不需要使用 asObservable()。 Subject 是 Observable,所以使用 asObservable() 只会用另一个 Observable 包裹它,这是不必要的。

还有一件事。在 Angular 5 中,有一个错误会在使用 EventEmitter 链接运算符时造成内存泄漏(链未正确处理)。有关详细信息,您可以在此处查看 https://github.com/angular/angular/issues/21999

这已在此处修复 https://github.com/angular/angular/pull/22016,应该可以从 Angular 6.

开始使用

而且我认为这正是您现在正在做的事情。在 Angular 6 之前避免这种情况的一种简单方法是在添加任何运算符之前实际使用 asObservable()(请参阅此注释 https://github.com/angular/angular/issues/21999#issuecomment-362921475)。