デバウンスデコレータ
debounce(f, ms)
デコレータの結果は、f
への呼び出しを、ms
ミリ秒の非アクティブ期間(呼び出しなし、「クールダウン期間」)になるまで一時停止し、その後、最新の引数でf
を一度呼び出すラッパーです。
言い換えると、debounce
は「電話を受け付け」、静かな状態がms
ミリ秒続くまで待つ秘書のようなものです。そして、そのとき初めて最新の通話情報を「上司」(実際のf
)に転送します。
例えば、関数f
があり、それをf = debounce(f, 1000)
で置き換えたとします。
その後、ラップされた関数が0ms、200ms、500msで呼び出され、その後呼び出しがない場合、実際のf
は1500msに一度だけ呼び出されます。つまり、最後の呼び出しから1000msのクールダウン期間後です。
…そして、最後の呼び出しの引数を受け取ります。他の呼び出しは無視されます。
そのためのコードを次に示します(Lodashライブラリのdebounceデコレータを使用しています)。
let f = _.debounce(alert, 1000);
f("a");
setTimeout( () => f("b"), 200);
setTimeout( () => f("c"), 500);
// debounced function waits 1000ms after the last call and then runs: alert("c")
では、実用的な例を見てみましょう。ユーザーが何かを入力し、入力の完了時にサーバーにリクエストを送信したいとします。
入力された文字ごとにリクエストを送信しても意味がありません。代わりに待機してから、結果全体を処理したいと考えています。
ウェブブラウザでは、イベントハンドラ(入力フィールドの変更ごとに呼び出される関数)を設定できます。通常、イベントハンドラは、入力されたキーごとに非常に頻繁に呼び出されます。しかし、それを1000msでdebounce
すると、最後の入力から1000ms後、一度だけ呼び出されます。
このライブ例では、ハンドラは結果を下のボックスに入力します。試してみてください。
ご覧のとおり、2番目の入力はデバウンスされた関数を呼び出すため、その内容は最後の入力から1000ms後に処理されます。
そのため、debounce
は、キー押下、マウスの動き、その他のイベントシーケンスを処理するのに最適な方法です。
最後の呼び出し後、指定された時間待機し、結果を処理できる関数を実行します。
課題は、debounce
デコレータを実装することです。
ヒント:少し考えれば、ほんの数行です :)
function debounce(func, ms) {
let timeout;
return function() {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, arguments), ms);
};
}
debounce
への呼び出しは、ラッパーを返します。呼び出されると、指定されたms
後に元の関数の呼び出しをスケジュールし、前のそのようなタイムアウトをキャンセルします。