デバウンスとスロットルを図で比較
デバウンスとスロットルの可視化ツール
JavaScriptのデバウンスとスロットルを図で比較 | We.Inc
パッド上でポインターを動かすと、生のイベント、デバウンス後とスロットル後の呼び出しを1本のタイムラインで確認できます。コピーできるデバウンス関数、スロットル関数、Reactフックも掲載しています。
デバウンスは、呼び出しが一定時間止まるまで待ってから1回だけ実行するため、検索ボックスや自動保存に向いています。スロットルは、呼び出しが続いている間も一定間隔ごとに最大1回実行するため、スクロール、リサイズ、ポインターの追跡に向いています。どちらも関数とミリ秒単位の遅延を受け取り、代わりに呼び出すラップ済みの関数を返します。
どちらを使うべきか
- 入力に合わせた検索
- デバウンス、約300 ms
- 入力が止まった後にリクエストを1回だけ送る
- フォームの自動保存
- デバウンス、約1000 ms
- 入力が落ち着いたら1回保存する
- スクロール位置や進捗バー
- スロットル、約100 ms
- スクロール中も定期的に更新する
- ウィンドウのリサイズに伴うレイアウト計算
- スロットルまたはデバウンス
- リアルタイムの反映ならスロットル、最終サイズだけならデバウンス
- 送信ボタンの二重クリック防止
- 先頭エッジのデバウンス
- 最初のクリックだけを有効にし、繰り返しは無視する
この2つの言葉が混同されやすいのは、どちらも関数の実行回数を減らす仕組みだからです。下のパッドでは、共通のタイムライン上で違いを確認できます。生のイベントは細い目盛り、デバウンスされた呼び出しとスロットルされた呼び出しはドットで表示されます。遅延を変えると、パターンもそれに合わせて変わります。
- パッドの上でポインターや指を動かすか、パッドにフォーカスした状態でキーを押し続けます。
- 上のレーンには生のイベントが並びます。中央のレーンにはデバウンスされた呼び出し、下のレーンにはスロットルされた呼び出しが表示されます。
- 遅延のスライダーを動かしてもう一度試し、間隔によって両方のパターンがどう変わるかを確認します。
- 下に掲載しているシンプルな関数やReactフックをコピーして、自分のコードで使えます。
- デバウンスされた関数は1回だけ作成しましょう。Reactのレンダリングのたびに新しく作るとタイマーがリセットされ、いつまでも実行されません。
- コンポーネントのアンマウント時には保留中の呼び出しをキャンセルしましょう。そうしないと、遅れて届いた呼び出しがすでに存在しないものを更新しようとする場合があります。
- スクロールに連動するアニメーションでは、固定間隔のスロットルよりrequestAnimationFrameのほうが適していることがよくあります。
- デバウンスするのはネットワークリクエストのような重い処理にしましょう。入力欄自体の状態をデバウンスすると、入力がもたついて感じられます。
よくある質問
デバウンスとスロットルの違いは何ですか?
デバウンスは呼び出しのたびにタイマーをリセットし、呼び出しが止まってから1回だけ実行します。スロットルは現在の時間枠内の呼び出しを無視しますが、枠が過ぎるとすぐに再び実行するため、長く続く連続呼び出しの間も一定の間隔で実行されます。
先頭エッジと末尾エッジとは何ですか?
先頭エッジは連続呼び出しの最初の呼び出し、末尾エッジはその連続呼び出しの間隔が終わる瞬間です。末尾エッジのデバウンスは呼び出しが止まった後に実行され、先頭エッジのデバウンスはすぐに実行して、その後は止まるまで呼び出しを無視します。スロットルはどちらかのエッジ、または両方で実行できます。
デバウンスにはlodashが必要ですか?
いいえ。このページの関数はそれぞれ数行で書けます。ライブラリ版にはmaxWait、cancel、flushなどのオプションがあり便利ですが、必要なものが1つだけなら自分で追加するのも簡単です。
遅延はどれくらいにすべきですか?
唯一の正解はありません。入力なら約300ミリ秒、スクロールやポインター操作なら約100ミリ秒から始めて、体感で調整しましょう。短くすると反応は良くなりますが、削減できる処理は少なくなります。
デバウンスの仕組み
- 呼び出しのたびに保留中のタイマーをクリアし、新しいタイマーを開始します。タイマーが遅延時間いっぱいまで残ったときだけ、最後の呼び出しの引数を使って元の関数が実行されます。
- そのため、デバウンスは意図をとらえるのに最適です。1回ごとのキー入力ではなく、入力し終えた単語だけが重要な場合に向いています。代償は遅延で、入力が止まるまでは何も起こりません。
スロットルの仕組み
- スロットルは最後に実行した時刻を覚えています。間隔内の呼び出しは破棄されるか、末尾エッジ版では間隔の終わりに実行するよう保存されます。間隔外の呼び出しはすぐに実行されます。
- スクロールに反応する固定ヘッダーのように、ユーザーに途切れないフィードバックを見せたいものの、すべてのイベントで実行すると無駄が多い場合に使います。
素のJavaScript版
debounce(fn, wait)
末尾エッジで実行します。cancel()で保留中の呼び出しを破棄できます。
throttle(fn, wait)
先頭エッジで実行し、その間に呼び出しがあれば時間枠の終わりにもう一度実行するため、最後の値が失われることはありません。
Reactフック
useDebouncedCallback
コンポーネントが存在する間は1つのタイマーを保持し、常に最新のコールバックを呼び出し、アンマウント時にタイマーをクリアします。
useThrottledValue
頻繁に変わる値のコピーを返し、そのコピーは間隔ごとに最大1回だけ更新されます。
生のイベント
デバウンス({n} ms)
スロットル({n} ms)
可視化ツール
パッドの上で動かしてください。細い目盛りは生のイベント、ドットはデバウンスやスロットルを経て実際に実行された呼び出しです。
遅延:{n} ms
イベントパッド:ここでポインターを動かすか、キーを押し続けてください
ここで動かす(またはフォーカスしてキーを押し続ける)
タイムラインには直近6秒が表示され、数値はその時間内の呼び出し回数です。
クリア
無料で始める · クレジットカード不要
関連: ガイド|Webマーケティングと集客を学ぶ
製品
ご利用いただける方
機能
リソース
会社情報
サイトマップを見る