代码之家  ›  专栏  ›  技术社区  ›  Jaroslaw K.

如何取消订阅@输出为可见

  •  1
  • Jaroslaw K.  · 技术社区  · 6 年前

    我有一个关于退订的问题 Output s呈角度。我知道EventEmitter会自动清理,但上次我需要使用时 Observable 作为我的 输出 。我是说,我想 输出 每秒最多发出一次事件。所以我的代码看起来像:

    @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');
    }
    

    好吧,它工作得很好——我想。唯一的问题是取消订阅。我发现 one solution 关于StackOverflow,但我仍然不确定应该如何正确执行。就我而言:

    @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) 有什么意义吗?或者也许 .asObservable() 确保当 Subject 是否已完成?有人知道我问题的答案吗?或者,也许有更好的解决方案,然后使用 可观察到 输出 ,我的案子?

    1 回复  |  直到 6 年前
        1
  •  3
  •   martin    6 年前

    如果要使用 takeUntil notifier Observable需要发出 next 通知,而不仅仅是完成。因此,正确的方法如下:

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

    您也不需要使用 asObservable() 在这种情况下。受试者是可观察的,因此使用 asObservable() 只会用另一个不必要的可见物来包装它。

    还有一件事。在Angular 5中,有一个bug在将操作符链接到 EventEmitter (链条处理不当)。有关更多详细信息,请查看此处 https://github.com/angular/angular/issues/21999

    此处已修复 https://github.com/angular/angular/pull/22016 并且应该从角度6开始提供。

    我想这正是你现在正在做的。在Angular 6实际使用 asObservable() 添加任何运算符之前(请参阅此注释 https://github.com/angular/angular/issues/21999#issuecomment-362921475 )。