组件内部使用Subject是否需要手动取消订阅?
@Component({ selector: 'app-home2', templateUrl: './home2.component.html', styleUrls: ['./home2.component.scss'] }) export class Home2Component implements OnInit { randNumberSub: BehaviorSubject<number> = new BehaviorSubject<number>( Math.random() ); ngOnInit() { this.randNumberSub.subscribe((data) => { console.log(`Sample1Component ==> RandomNumber: ${data}`); }); } onClick() { this.randNumberSub.next(100); } }
组件内部Subject的订阅不会自动取消
哪怕Subject是组件内部声明的,组件销毁时不会自动取消对它的订阅。原因很直接:Angular组件销毁时只会清理自身实例的核心资源,但不会主动遍历并取消组件内所有Observable的订阅——订阅关系是独立于组件实例存在的,只要订阅没被取消,回调函数就会一直持有组件实例的引用,进而引发内存泄漏。
比如你这段代码里,组件销毁后如果randNumberSub还没被垃圾回收,之前的订阅回调依然会保留对组件实例的引用,内存就没法被正常释放。
正确的处理方式
有几种简单可靠的方案:
使用
takeUntil操作符统一管理:声明一个用于标记组件销毁的Subject,在ngOnDestroy中发出完成信号,所有手动订阅都通过这个操作符自动取消destroy$ = new Subject<void>(); ngOnInit() { this.randNumberSub .pipe(takeUntil(this.destroy$)) .subscribe((data) => { console.log(`Sample1Component ==> RandomNumber: ${data}`); }); } ngOnDestroy() { this.destroy$.next(); this.destroy$.complete(); // 同时完成组件内的Subject,彻底释放相关资源 this.randNumberSub.complete(); }保存订阅对象,销毁时手动取消:
private subscription!: Subscription; ngOnInit() { this.subscription = this.randNumberSub.subscribe((data) => { console.log(`Sample1Component ==> RandomNumber: ${data}`); }); } ngOnDestroy() { this.subscription.unsubscribe(); this.randNumberSub.complete(); }
如果是用Angular的async管道做订阅,它会自动在组件销毁时取消订阅,但你这里是手动调用subscribe(),所以必须自己处理订阅的取消。
内容的提问来源于stack exchange,提问作者Ilya
相关产品推荐
相关产品推荐

