什麼是去抖動器,為什麼它很重要

去抖動器是一種編程模式,用於確保耗時任務不會過於頻繁地觸發,從而防止性能問題或服務器因請求過載。這在諸如搜索輸入等場景中特別有用,在這些場景中,您可能不希望每次按鍵都觸發搜索請求,而是希望在用戶暫停輸入後再觸發。

通過實現去抖動器,您可以同時增強用戶體驗和應用程序效率。這是通過將函數的執行延遲到自上次調用以來經過指定的時間來實現的。

何時使用去抖動器

當您想限制函數調用的頻率時,最好使用去抖動器。常見用例包括:

  • 用戶輸入驗證:延遲驗證,直到用戶停止輸入,以避免每次按鍵都進行不必要的處理。
  • 搜索功能:等到用戶完成輸入搜索查詢後再開始搜索過程,從而減少發送到服務器的搜索請求數量。
  • 窗口大小調整:限制瀏覽器窗口大小調整時重新計算或調整的次數。

如何在 Qwik 中實現去抖動器

Qwik 框架提供獨特的功能,以可序列化和高效的方式管理狀態和效果。在 Qwik 中實現去抖動器涉及使用 Qwik 的原語,例如用於狀態管理的 useSignal 和用於標記可以在不破壞序列化的情況下捕獲狀態的函數的 $。下面是一個簡單的去抖動器模式。它的行為類似於基於閉包的去抖動器,這些去抖動器在達到超時時執行函數。

export const useDebouncer = (fn: QRL<(args: any) => void>, delay: number) => {
  const timeoutId = useSignal<number>();
 
  return $((args: any) => {
    clearTimeout(timeoutId.value);
    timeoutId.value = Number(setTimeout(() => fn(args), delay));
  });
};

此去抖動器將函數和延遲作為參數。它利用 useSignal 來跟踪 timeoutID,確保與 Qwik 的可恢復性模型及其對 QRL 的使用兼容。返回的函數在被調用時,會清除任何現有的超時,並設置一個新的超時,以在指定的延遲後調用提供的函數。

如何使用去抖動器

以下示例演示如何在組件中使用去抖動器來有效地管理用戶輸入。通過對輸入進行去抖動,應用程序僅在用戶停止輸入 1 秒後才更新狀態,從而優化 API 調用或數據過濾等操作的性能。

import { $, useSignal, component$, type QRL } from "@builder.io/qwik";
import { useDebouncer } from "~/utils/debouncer";
 
export default component$(() => {
  const debouncedValue = useSignal("");
 
  const debounce = useDebouncer(
    $((value: string) => {
      debouncedValue.value = value;
    }),
    1000
  );
 
  return (
    <>
      <input
        onInput$={(_, target) => {
          debounce(target.value);
        }}
      />
      <p>{debouncedValue.value}</p>
    </>
  );
});

實時演示

在下面的實時演示中,useDebouncer 用於在自上次按鍵以來經過 1 秒的延遲後更新 debouncedValue 信號。

獎勵:useDebouncer$

為我們的開發人員節省額外的“用 $() 包裹”操作。

我們可以利用 Qwik 的 implicit$FirstArg 函數來創建一個 useDebouncer$ 函數,該函數會自動使用 $() 包裹提供的函數。

這就是 Qwik 實際實現其所有內置 $ 鉤子的方式。

export const useDebouncerQrl = (fn: QRL<(args: any) => void>, delay: number) => {
  const timeoutId = useSignal<number>();
 
  return $((args: any) => {
    clearTimeout(timeoutId.value);
    timeoutId.value = Number(setTimeout(() => fn(args), delay));
  });
};
 
export const useDebouncer$ = implicit$FirstArg(useDebouncerQrl);

現在我們可以這樣做

const debounce = useDebouncer$(
  (value: string) => {
    debouncedValue.value = value;
  },
  1000
);

很棒,對吧?:)

貢獻者

感謝所有幫助改進本文檔的貢獻者!

  • n8sabes
  • KenAKAFrosty
  • shairez