iT邦幫忙

2024 iThome 鐵人賽

0
JavaScript

Signal API in Angular系列 第 43

Day 44 - toSignal 函數的初始值

  • 分享至 

  • xImage
  •  

Observable 是惰性的;因此,除非被訂閱,否則它不會發出值。另一方面,訊號始終具有值,包括 toSignal 函數建立的訊號。雖然 toSignal 函數追蹤 Observable,但它仍然需要一個初始值,直到 Observable 發出第一個值。預設情況下,初始值 undefined,但可以透過 ToSignalOptionsinitialValue 選項覆寫。

interface ToSignalOptions<T> {
 initialValue?: unknown;
 requireSync?: boolean | undefined;
 injector?: Injector | undefined;
 manualCleanup?: boolean | undefined;
 rejectErrors?: boolean | undefined;
 equal?: ValueEqualityFn<T> | undefined;
}

在這篇文章中,我示範了向 toSignal 函數提供自訂初始值的兩個範例。

  • 追蹤第一次點擊發生之前經過的秒數。
  • 緩衝文件中最後兩次按鈕點擊並顯示 clientXclientY 的值。

toSignal 函數中提供初始值時,程式碼可以避免未定義的錯誤或在範本中指定預設值。 這取決於開發人員的偏好,但我更喜歡使用 intialValue 選項從訊號類型中刪除 undefined

追蹤第一次點擊之前經過的秒數

document$ = inject(DOCUMENT);
click$ = fromEvent(this.document$, 'click')
    .pipe(shareReplay({ bufferSize: 1, refCount: true }));
secondsBeforeFirstClick$ = interval(1000)
     .pipe(takeUntil(this.click$));
numSeconds$ = this.secondsBeforeFirstClick$.pipe(count());

當使用者按一下文件時,click$ Observable 會發出 MouseEvent。 secondsBeforeFirstClick$ Observable 每秒發出一個整數,在第一次點擊發生時取消訂閱。 numSeconds$ Observable 計算第一次點選發生前經過的秒數。

numSecondsUndfined = toSignal(this.numSeconds$)
numSeconds = toSignal(this.numSeconds$, { initialValue: 0 });

toSignal函數建立numSecondsUndefinednumSeconds訊號。前者的類型是Signal<number|undefined>,而後者的類型是Signal<number>。如果沒有initialValue選項,則numSecondsUndefined訊號的初始值是undefined。numSeconds訊號的初始值為零,因為 initialValue的選項值為零。

<div class="region">
     @let value = numSecondsUndfined() ?? 0;
     <p>Undefined initial value. Number of seconds before click: {{ value }}</p>
</div>

<div class="region">
     <p>Use initialValue option. Number of seconds before click: {{ numSeconds() }}</p>
</div>

HTML 範本在第一次點擊之前顯示相同的數值 (0)。但是,我聲明了一個 @let 變數來應用nullish coalescing (??) 運算符,以便在 numSecondsUndefined 訊號未定義時傳回 0。 相比之下,numSeconds訊號傳回一個數字,程式碼稍微清晰一些。

顯示最後兩次按鈕點擊

mouseXY$ = this.click$.pipe(
   filter((e) => e instanceof MouseEvent),
   map((e) => e as MouseEvent),
   map(({ clientX, clientY }) => ({ x: clientX, y: clientY }))
);
bufferClicks$ = this.mouseXY$.pipe(bufferCount(2));
strClicks$ = this.bufferClicks$.pipe(
   map((results) => results.map(({ x, y }) => `(${x}, ${y})`))
);
strClicksUndefined = toSignal(this.strClicks$);
strClicks = toSignal(this.strClicks$, { initialValue: [] });

mouseXY$ Observable 會發出每次滑鼠點選的 clientXclientY值。 bufferClicks$ 發出一個緩衝區,其中保存了前兩次滑鼠點擊。 strClicks$ Observable 發出 X 和 Y 值的字串陣列。 strClick 訊號最初值是一個 empty array。 strClickUndefined 訊號最初值是 undefined。

<div class="fib">
     @let xyValues = strClicksUndefined() ?? [];
     <p>Undefined initial value. Show the last 2 clicks: {{ xyValues.join(', ') }}</p>
     <p>Show the last 2 clicks: {{ strClicks().join(', ') }}</p>
</div>

HTML範本在前兩次點擊之前顯示一個空白字串。但是,我聲明了一個 @let 變數來應用nullish coalescing (??) 運算符,以便在 strClicksUndefined 訊號是undefined時傳回空陣列。 strClickssignal 會跳過此檢查,因為它總是會傳回一個陣列。

結論:

  • ToSignalOptions有一個initialValue屬性來覆寫undefined的預設值。
  • toSignal函數的回傳類型為T | undefined,如果沒有initialValue屬性。
  • toSignal函數有第二個參數時,回傳類型是T。
  • 透過指定初始值,程式碼可以避免 HTML 範本中的未定義錯誤和nullish coalescing(??)。

參考:


上一篇
Day 42 - toSignal 函數中的相等性檢查
系列文
Signal API in Angular43
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言