頻繁にイベントが起きるもので 実行回数を抑えたいときがあります
数行書けばできるので自分でタイマー制御してることがほとんどです
ただ 使うライブラリによってはそういう機能をユーティリティ関数として提供してる場合もあります
これのためにわざわざライブラリをインストールしようとは思わないですが すでに使ってるライブラリに機能があるならそれを使おうと思います
機能名は debounce と throttle という名前になってるのをよく見ます
lodash から有名になったと思いますが 元になった underscore.js でも実装されていたものです
実装の経緯を見ると underscore.js が最初ではなくすでに jQuery プラグインなどで存在した機能のようです
https://github.com/jashkenas/underscore/issues/66
2 種類あるのは知ってるのですが 普段使いしてないとどっちがどういう動きするのかわからなくなります
debounce
これは関数の実行を指定時間分遅延します
1 回呼び出すだけなら setTimeout と同じです
指定の時間後に 1 度実行されます
複数回呼び出す場合 遅延している間にもう一度呼び出すとタイマーをクリアして再セットします
遅延時間内に関数を呼び出し続けると永遠に実行されません
また必ず最後の呼び出しから遅延時間分は遅れて実行されます
実装によってはオプションで 連続で呼び出し続けても何秒に 1 回は実行されるようにする最大遅延時間が指定できたりします
また タイマーをキャンセルしたり即時実行したりできるものもあります
throttle
こっちは指定時間の間は実行されないようにするものです
1 回目の呼び出しでは即自に実行されます
それから指定の時間の間は呼び出しても実行されず 前回の実行から指定時間の経過後に実行されます
なので呼び出し続けても指定時間に 1 回は実行されます
また 次の実行は前回の実行から指定時間後なので 指定時間の経過直前で呼び出すと 遅延はするものの呼び出してからすぐに実行される場合もあります
lodash の実装の場合は debounce と throttle の実装は共通になっていて デフォルトのオプションが異なるだけです
オプションで 実行しない期間に入るタイミング (leading) と実行しない期間の終わりのタイミング (trailing) で関数を実行するかを選べるようになっています
両方とも実行しない場合は一切関数が実行されない挙動になります
debounce のデフォルトは trailing のみの実行です
throttle のデフォルトは leading と trailing の両方かつ 最大遅延時間を遅延時間と同じにしています
連続で呼び出し続けてる間は全く実行されなくていい場合は debounce
連続で呼び出し続けても適度な間隔で実行されて欲しいなら throttle
という使い分けでいいと思います
そういえば以前 input 要素が idle イベントと timeout イベントを起こすようにしました
🔗 input で idle イベントを起こす
入力が終わって指定時間(idle)後に idle イベントが発生します
入力を続けている間は起きません
入力をずっと続けている間に 指定時間(timeout)が経過すると timeout イベントが発生します
debounce は idle イベントにリスナを付けるのと同じ感じです
throttle は timeout イベントにリスナを付けるのと同じ感じです
ただ timeout なので入力開始時にはイベントが起きなくてそこだけは違います