第1引数の関数を設定して、1回目は即時発動して2回目以降は、第2引数の時間後発動(単位はミリ秒)。その間の関数発動は一番最後に受け付けた関数のみ発動する関数を返す。
■使用例
function logged( txt ){
var text = _.now();
console.log( "re now : " + txt + " : " + text );
}
var re = _.throttle( logged, 5000 );
// 即時発動。re now : 0 : 1430734386522
re("0");
re("1");
re("2");
re("3");
re("4");
// re("1") 〜 re("4") までは発動しない。第2引数の時間後 re("5") 発動。 re now : 5 : 1430734391523
re("5");
■内部構造
_.throttle = function(func, wait, options) {
var context, args, result;
var timeout = null;
var previous = 0;
// 第3引数が指定されていなかったら
if (!options) options = {};
// _.throttle設定後の最初の関数発動時のsetTimeout関数で呼ばれる関数。
var later = function() {
// later()発動後は 0 が再度設定される。
previous = options.leading === false ? 0 : _.now();
timeout = null;
// context を this にした func( args ) が設定される。
result = func.apply(context, args);
// timeout = null;
if (!timeout) context = args = null;
};
// _.throttle() 設定時に返される関数。使用例の re("1") の引数はこの関数の引数。
return function() {
var now = _.now();
// ここは無視。第3引数が設定されている時なので。
if (!previous && options.leading === false) previous = now;
// 残り時間が設定される。(関数が発動される度に。)_.throttle() 設定後の最初の関数発動時は previous = 0;
var remaining = wait - (now - previous);
// _.throttle() を設定した関数がメソッドでないのであれば this = グローバルオブジェクト。
context = this;
// 返される関数の引数。
args = arguments;
// 残り時間が 0 以下か wait 時間を上まっていたらなのだが、
// _.throttle設定後の最初の関数発動時、remaining の数が 0 以下なの1回目はここを実行する。
if (remaining <= 0 || remaining > wait) {
// 最初は timeout = null; なので
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
previous = now;
// context を this に設定した func( args ) 関数。
result = func.apply(context, args);
// 最初は timeout = null; なので
if (!timeout) context = args = null;
} else if (!timeout && options.trailing !== false) {
// _.throttle設定後の2回目以降関数発動時に setTimeout が呼ばれる。
timeout = setTimeout(later, remaining);
}
// _.throttle設定後の関数で発動する関数。
// wait時間の間のキャンセルされる関数は undefined が返される。
return result;
};
};