问题原因
待调查, 欢迎小伙伴参与讨论~
问题描述
为了避免造成内存泄漏,long lived observable 都需要unsubscribe,一般使用takeWhile 和 takeUntil。但是在使用过程中发现有的时候takeWhile 不能正常工作,不知道为什么??
主体代码如下,takeUntil(notifier)
可以正常工作,但是换成takeWhile(() => this.alive)
则不能成功打印出form statusChange complete
。
import { Component, Input, OnChanges, OnDestroy, OnInit } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { Subject } from 'rxjs';
import { debounceTime, takeUntil, takeWhile } from 'rxjs/operators';
@Component({
selector: 'dialog',
templateUrl: './dialog.component.html',
})
export class DialogComponent implements OnInit, OnChanges, OnDestroy {
@Input() innerForm?: FormGroup;
destory$ = new Subject();
constructor() { }
ngOnInit(): void {}
ngOnChanges(): void {
if (this.innerForm) {
this.innerForm.statusChanges.pipe(takeUntil(this.destory$)).subscribe((status) => {
console.log('form statusChange next', status);
}, (err) => {
console.log('form statusChange error', err);
}, () => {
console.log('form statusChange complete');
});
}
}
ngOnDestroy(): void {
// 如果没有这句话直接complete 的话,并不会打印form statusChange complete
this.destory$.next();
// 这句可有可无,只要有上面这句,takeUntil 就会让source observable complete. 也有文章说complete 必须调用,否则也有内存泄漏的风险,不知道为什么??试验下来确实会打印form statusChange complete
this.destory$.complete();
}
}
takeWhile 和 takeUntil 介绍
takeWhile
比较惊奇的一点是,之前一直以为takeWhile(condition)
, 只要condition 为true 就能从source observable
emit出来值,但是经过试验发现,当condition fail 之后,source observable
就被block 住了,即使后面的source observable
能满足条件,也不会emit 出新值了。下面的图比较形象的解释了takeWhile
。
takeUntil
takeUntil(notifier)
使用于source observable
受另一个notifier observable
的控制来emit 值的,当notifier observable
发出第一个值的时候,source observable
停止emit 新值。如下图notifier observable
为timer(5000)
,5s 之后source observable
停止了emit新值。
以上图片是来自附录参考文章【RxJS — take vs takeLast vs takeWhile vs takeUntil operators】,感谢文章作者Vinodhec