throttleとdebounce
throttle
とdebounce
といきなり言われてピンとくる人もそうでない人も、ここらでおさらいしませんか? という回です。これらが何なのか、どう使うのか、どう実装するのかを今一度確認していきましょう。
なぜ今更こんなことをするのかというと、自分が先日忘れていたからです😳
ナニコレ
throttle
とdebounce
とは、簡単に言うと間引き処理の一種です。連続して大量に繰り返される処理を間引いて負荷を軽減させたりするときに使います。
throttle
連続して大量に繰り返される処理を一定感覚で間引くものです。
よく使われるのはscrollイベントです。スクロールイベントをすべてハンドリングすると処理回数が多くなり、場合によってはスクロールがもっさりしてしまいますよね。それを防ぎます。
debounce
連続して大量に繰り返される処理が指定時間内に何度発生しても最後の1回だけ実行するものです。 よく使われるのはresizeイベントです。「ウインドウサイズが変わったときに要素のサイズを変える」みたいなケースってありますよね。その時、ウインドウの端っこをつまんでぐりぐりとドラッグするイベントを全て取得しても意味がありません。マウスから手を話しresizeが完了したときのイベントをとれば十分です。
つくりかた
throttle
export function throttle(fn, delay) {
let timerId;
let lastExecTime = 0;
return () => {
const context = this;
const args = arguments;
let elapsedTime = performance.now() - lastExecTime;
const execute = () => {
fn.apply(context, args);
lastExecTime = performance.now();
}
if (!timerId) {
execute();
}
if (timerId) {
clearTimeout(timerId);
}
if (elapsedTime > delay) {
execute();
} else {
timerId = setTimeout(execute, delay);
}
}
}
throttle
関数が呼び出される最初の1回と、elapsedTime(経過時間)
が指定の間引き時間を上回るときと、最後の1回が実行されます。説明を読むよりソースを読むほうが分かりやすいですね。
debounce
export function debounce(fn, interval) {
let timerId;
return () => {
clearTimeout(timerId);
const context = this;
const args = arguments;
timerId = setTimeout(() => {
fn.apply(context, args);
}, interval);
}
}
setTimeout
でinterval
の時間だけ処理を待っています。待っている間に連続してdebounce関数が実行されると、待っている処理をclearTimeout
してタイマーを再セットします。
こうすることで、interval
時間内に連続して行われる処理は、最後の1回だけが実行されます。
おわり
jQueryにもこれらの関数は用意されていますし、それ以外にも世の中にはたくさんのライブラリがあります。が、このくらいなら自分で書いてしまったほうがファイルサイズが小さくなって良いケースもあったりします。
適材適所、良しなにやっていきたいものですね☺