你可能知道當(dāng)你訂閱 Observable 對象或設(shè)置事件監(jiān)聽時(shí),在某個(gè)時(shí)間點(diǎn),你需要執(zhí)行取消訂閱操作,進(jìn)而釋放操作系統(tǒng)的內(nèi)存。否則,你的應(yīng)用程序可能會(huì)出現(xiàn)內(nèi)存泄露。
接下來讓我們看一下,需要在 ngOnDestroy 生命周期鉤子中,手動(dòng)執(zhí)行取消訂閱操作的一些常見場景。
手動(dòng)釋放資源場景
表單
export class TestComponent { ngOnInit() { this.form = new FormGroup({...}); // 監(jiān)聽表單值的變化 this.valueChanges = this.form.valueChanges.subscribe(console.log); // 監(jiān)聽表單狀態(tài)的變化 this.statusChanges = this.form.statusChanges.subscribe(console.log); } ngOnDestroy() { this.valueChanges.unsubscribe(); this.statusChanges.unsubscribe(); }}以上方案也適用于其它的表單控件。
路由
export class TestComponent { constructor(private route: ActivatedRoute, private router: Router) { } ngOnInit() { this.route.params.subscribe(console.log); this.route.queryParams.subscribe(console.log); this.route.fragment.subscribe(console.log); this.route.data.subscribe(console.log); this.route.url.subscribe(console.log); this.router.events.subscribe(console.log); } ngOnDestroy() { // 手動(dòng)執(zhí)行取消訂閱的操作 }}Renderer 服務(wù)
export class TestComponent { constructor( private renderer: Renderer2, private element : ElementRef) { } ngOnInit() { this.click = this.renderer .listen(this.element.nativeElement, "click", handler); } ngOnDestroy() { this.click.unsubscribe(); }}Infinite Observables
當(dāng)你使用 interval() 或 fromEvent() 操作符時(shí),你創(chuàng)建的是一個(gè)無限的 Observable 對象。這樣的話,當(dāng)我們不再需要使用它們的時(shí)候,就需要取消訂閱,手動(dòng)釋放資源。
export class TestComponent { constructor(private element : ElementRef) { } interval: Subscription; click: Subscription; ngOnInit() { this.interval = Observable.interval(1000).subscribe(console.log); this.click = Observable.fromEvent(this.element.nativeElement, 'click') .subscribe(console.log); } ngOnDestroy() { this.interval.unsubscribe(); this.click.unsubscribe(); }}Redux Store
export class TestComponent { constructor(private store: Store) { } todos: Subscription; ngOnInit() { /** * select(key : string) { * return this.map(state => state[key]).distinctUntilChanged(); * } */ this.todos = this.store.select('todos').subscribe(console.log); } ngOnDestroy() { this.todos.unsubscribe(); }}無需手動(dòng)釋放資源場景
AsyncPipe
@Component({ selector: 'test', template: `<todos [todos]="todos$ | async"></todos>`})export class TestComponent { constructor(private store: Store) { } ngOnInit() { this.todos$ = this.store.select('todos'); }}
新聞熱點(diǎn)
疑難解答
圖片精選