検索フォームや絞り込みUIで、入力のたびに重い処理やAPI通信を走らせると、画面がもたつきやすくなります。そこで使うのが debounce です。
debounceは、連続して発生する処理を少し待って、最後の1回だけ実行する考え方です。検索候補、絞り込み、入力チェック、リサイズ処理などでよく使います。
HTML
<label class="search-box">
記事を検索
<input id="keyword" type="search" placeholder="JavaScript、CSS、バスケ">
</label>
<ul id="results" class="result-list"></ul>
JavaScript
const input = document.querySelector("#keyword");
const results = document.querySelector("#results");
const posts = [
"JavaScriptでフォーム入力を検証する方法",
"CSS :focus-visibleの使い方",
"バスケのピックアンドロール入門",
"PHPでPDOのプリペアドステートメントを使う方法",
];
function debounce(callback, delay = 300) {
let timerId;
return (...args) => {
clearTimeout(timerId);
timerId = setTimeout(() => {
callback(...args);
}, delay);
};
}
function render(keyword) {
const value = keyword.trim().toLowerCase();
const filtered = posts.filter((post) => {
return post.toLowerCase().includes(value);
});
results.innerHTML = filtered
.map((post) => `<li>${post}</li>`)
.join("");
}
input.addEventListener("input", debounce((event) => {
render(event.target.value);
}, 300));
render("");
debounceを入れる場面
| 場面 | 理由 |
|---|---|
| 検索入力 | 1文字ごとに検索処理を走らせる必要がない |
| API通信 | 短時間にリクエストが増えるのを防ぐ |
| resize処理 | 画面サイズ変更中の連続実行を抑える |
| 入力プレビュー | ユーザーが止まってから反映すると見やすい |
実装の注意点
- 短すぎるdelayは効果が薄く、長すぎると反応が遅く感じる
- 検索UIなら200〜500msあたりから調整する
- 送信ボタンの二重送信防止にはdebounceよりdisabled制御が向いている
- API通信ではAbortControllerと組み合わせると古いリクエストも止めやすい