Week 09 · Day 05 — 記憶體管理:takeUntil

學習目標

  • takeUntil 自動停止訂閱
  • ngOnDestroy 完成清理
  • 避免因未退訂造成的記憶體洩漏

重點

問題:訂閱沒退訂 → 記憶體洩漏 - Observable 若沒退訂,元件銷毀後仍會觸發回呼 - 可能存取已銷毀的元件 → 錯誤或洩漏

用 takeUntil 清理

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

@Component({ ... })
export class SmartComponent implements OnInit, OnDestroy {
  private destroy$ = new Subject<void>();

  ngOnInit(): void {
    this.dataService.getData()
      .pipe(takeUntil(this.destroy$))   // destroy$ 結束時停止訂閱
      .subscribe(data => {
        this.data = data;
      });
  }

  ngOnDestroy(): void {
    this.destroy$.next();      // 通知所有 takeUntil 停止
    this.destroy$.complete();
  }
}

原理 - takeUntil(notifier$):當 notifier$ 發出 next 或 complete,就結束訂閱 - 在 ngOnDestroy 觸發 destroy$.next() → 所有掛 takeUntil 的訂閱自動退訂

最常見對策 - 所有呼叫 subscribe() 的地方都記得掛 takeUntil(this.destroy$) - destroy$ 是元件常見的慣用命名

實作

  1. 建立元件訂閱 getData()
  2. takeUntil(this.destroy$) 包住
  3. ngOnDestroy 執行 next() + complete()
  4. 切換頁面確認訂閱已停止(console 無殘留 log)

作業

  • 建立 destroy$ 並在 ngOnDestroy 觸發
  • 每個訂閱用 takeUntil 包住
  • 說明未退訂為什麼造成記憶體洩漏