デバウンスとスロットル

デバウンスとスロットルとは

キー入力・スクロール・ウィンドウリサイズのように高頻度で連続発生するイベントをそのままハンドラで処理すると、無駄な再計算やAPIリクエストが大量に走ってしまいます。これを間引く代表的な手法がデバウンススロットルです。

  • デバウンス — イベントが一定時間止まってから、まとめて1回だけ実行する
  • スロットル — 発生頻度に関わらず、一定間隔ごとに最大1回実行する

どちらも「間引く」目的は同じですが、間引き方が異なります。

違いの比較

手法挙動向いている用途
デバウンス最後の発火から一定時間後に1回実行入力が落ち着いたタイミングで動かしたい処理(自動保存、検索候補の取得)
スロットル一定間隔ごとに間引きつつ継続実行発生中も定期的に反映したい処理(スクロール追従、連続描画)

実装のポイント

デバウンスの基本形は「呼ばれるたびに前回のタイマーを解除し、新しいタイマーを仕掛け直す」だけです。

function debounce(fn, delay) {
  let timer
  return (...args) => {
    clearTimeout(timer)
    timer = setTimeout(() => fn(...args), delay)
  }
}

[[React]] のようなコンポーネント指向のUIでは、コンポーネントが破棄された後にタイマーが発火して存在しない画面を更新しようとしないよう、アンマウント時のタイマー解除(クリーンアップ)も忘れずに行います。

初学者向けポイント

  • 検索欄のオートコンプリート、フォームの自動下書き保存 → デバウンス向き(「入力が止まったら」実行したい)
  • ウィンドウリサイズ時のレイアウト再計算、無限スクロールの監視 → スロットル向き(「発生し続けている間も」定期的に反映したい)
  • 用途を取り違えると「保存が遅すぎる」「操作がカクつく」といった体感の悪さに直結する

関連技術とのつながり

  • [[JavaScript]] — setTimeout などのタイマーAPIで実装する
  • [[Webパフォーマンス最適化]] — 不要な処理を間引いて体感速度を上げる代表的な手法
  • [[状態管理]] — 間引いた結果をいつ状態に反映するかという設計と関わる
Q: 「入力が止まってから一定時間後に1回だけ実行する」手法はどちらか?
- [x] デバウンス
- [ ] スロットル
解説: デバウンスは最後の発火から一定時間後に1回だけ実行する手法です。自動保存や検索候補取得に向きます。

Q: スクロール位置の追従処理のように「発生中も定期的に反映したい」場合に向く手法はどちらか?
- [ ] デバウンス
- [x] スロットル
解説: スロットルは発生頻度に関わらず一定間隔ごとに実行するため、連続的なイベント中も定期的に反映したい処理に向きます。

Q: デバウンス・スロットルを使う主な目的は何?
- [x] 高頻度に発生するイベントの処理回数を間引き、無駄な再計算やリクエストを減らす
- [ ] イベントの発生順序を並び替える
- [ ] イベントリスナーの登録数を増やす
解説: どちらも高頻度イベントの処理回数を間引き、パフォーマンスを改善するための手法です。