Angular 5中不使用ngOnDestroy()取消自定义订阅的方法
嘿,针对你在Angular 5里不想用ngOnDestroy来取消订阅的需求,我给你几个实用的方案,结合你的代码来举例:
1. 利用async管道自动管理订阅(首推)
Angular的async管道是官方推荐的避免内存泄漏的方式,它会在组件销毁时自动帮你取消订阅,完全不用手动处理。
针对你的路由参数订阅,可以这么改:
import { tap } from 'rxjs/operators'; // 先在组件里定义一个Observable属性 branchId$: Observable<number>; ngOnInit() { this.branchId$ = this.activatedRoute.parent.params.pipe( tap(params => this.branchId = +params['id']) // 在这里完成参数赋值 ); this.validateAssignForm(); this.getConfirmReturnValue(); }
然后在组件的模板里随便找个地方(哪怕是隐藏的元素)用上这个Observable配合async管道:
<!-- 只是用来触发async管道的订阅,不用显示内容 --> <div *ngIf="branchId$ | async"></div>
这样路由参数的订阅就完全不用你手动取消了,管道会帮你处理好。
对于你的自定义订阅subscription1,也可以用同样的思路:
confirmReturnValue$: Observable<any>; getConfirmReturnValue() { this.confirmReturnValue$ = this.confirmService.getReturnValue().pipe( tap(suc => { console.log('return value::', suc); if (suc != 0 && suc.hasOwnProperty('returnValue')) { this.deleteLanguage(suc); } }) ); }
同样在模板里加一行:
<div *ngIf="confirmReturnValue$ | async"></div>
2. 用take(1)/first()操作符(适合只需要一次值的场景)
如果你的父路由参数在组件生命周期内不会变化,或者你只需要获取一次初始值,那可以给Observable添加take(1)操作符——它会在获取第一个值后自动取消订阅:
import { take } from 'rxjs/operators'; ngOnInit() { this.activatedRoute.parent.params.pipe( take(1) ).subscribe( params => this.branchId = +params['id'] ); this.validateAssignForm(); this.getConfirmReturnValue(); }
如果confirmService.getReturnValue()也只会发射一次值,你也可以给它加take(1):
getConfirmReturnValue() { this.confirmService.getReturnValue().pipe( take(1) ).subscribe( suc => { console.log('return value::', suc); if (suc != 0 && suc.hasOwnProperty('returnValue')) { this.deleteLanguage(suc); } } ); }
3. 用takeWhile操作符(适合需要条件终止的场景)
如果你的自定义订阅需要在某个条件满足后才取消(比如处理完一次返回值就不再订阅),可以用takeWhile:
import { takeWhile } from 'rxjs/operators'; // 先定义一个控制订阅的布尔属性 isSubscribed = true; getConfirmReturnValue() { this.confirmService.getReturnValue().pipe( takeWhile(() => this.isSubscribed) ).subscribe( suc => { console.log('return value::', suc); if (suc != 0 && suc.hasOwnProperty('returnValue')) { this.deleteLanguage(suc); // 处理完后终止订阅 this.isSubscribed = false; } } ); }
这种方式不需要ngOnDestroy,你可以在任意你想终止订阅的时机把isSubscribed设为false。
内容的提问来源于stack exchange,提问作者Santhosh
相关产品推荐
相关产品推荐

