Signal 與 Observable 的轉換

Angular 提供了兩個實用的函數來在 Signal 與 Observable 之間進行轉換,這些函數位於 @angular/core/rxjs-interop 套件中。

Signal 轉 Observable

toObservable() 接收一個 signal,並將其轉換為 Observable。

import { toObservable } from '@angular/core/rxjs-interop';

clickCount = signal(0);
clickCount$ = toObservable(this.clickCount);

const subscription = this.clickCount$.subscribe({
  next: (val) => console.log(`Current click count: ${val}`),
});

// 記得在組件銷毀時取消訂閱
this.destroyRef.onDestroy(() => {
  subscription.unsubscribe();
});

注意事項:

  • 傳入的是 signal 本身,不要加括號執行它

  • 這樣創建的 observable 會在 signal 值更新時發出新值

Observable 轉 Signal

toSignal() 接收一個 observable,並將其轉換為 Signal。

import { toSignal } from '@angular/core/rxjs-interop';

interval$ = interval(1000);
intervalSignal = toSignal(this.interval$);

轉換後的 intervalSignal 就可以像一般的 Signal 一樣使用:

  • 在 effect 中被捕捉

  • 用於 computed 計算

  • 在模板中直接呼叫顯示

<p>
  intervalSignal: {{ intervalSignal() }}
</p>

初始值處理: 由於 observable 可能沒有初始值,轉換出的 signal 一開始可能是 undefined。載入頁面時,需要等待 observable 第一次發出值才會顯示。

如果想要指定初始值,可以傳入第二個參數:

intervalSignal = toSignal(this.interval$, { initialValue: 0 });

自動清理: 使用 toSignal 轉換的 Observable,Angular 會自動處理訂閱的清理工作,不需要手動呼叫 unsubscribe()。

使用場景

這些轉換函數特別適合在以下情況使用:

  1. 與現有 RxJS 程式碼整合:在逐步導入 Signal 的專案中

  2. 混合使用兩種模式:同時利用 RxJS 的操作符和 Signal 的簡潔性

  3. 逐步遷移:將舊的基於 Observable 的程式碼遷移到新的 Signal 架構

效能考量

  • Signal 通常比 Observable 有更好的效能,特別是在變更偵測方面

  • 在頻繁更新的 UI 元件中,考慮將關鍵的 Observable 轉換為 Signal

Last updated