ikemonn's blog

技術ネタをちょこちょこと

【Underscore.js】_.throttleを読んだ

jashkenas/underscore_.throttleを読んだ。

概要

_.throttle(function, wait, [options])

functionを一度目は即時実行して、二回目以降はwaitミリ秒待ってから実行する関数を返す。waitミリ秒までに複数回関数を実行しようとしても、最後に受け付けた関数のみが実行される。

function printCurrTime(num) {
    console.log(`now: ${_.now()} num: ${num}`);
}

var printTime = _.throttle(printCurrTime, 5000);

printTime(0);
printTime(1); // 実行されない
printTime(2); // 実行されない
printTime(3); // 実行されない
printTime(4); // 実行されない
printTime(5);


// now: 1445396803605 num: 0
// now: 1445396808607 num: 5

ソースコード

_.throttle = function(func, wait, options) {
    var context, args, result;
    var timeout = null;
    var previous = 0;
    if (!options) options = {};
    var later = function() {
      previous = options.leading === false ? 0 : _.now();
      timeout = null;
      result = func.apply(context, args);
      if (!timeout) context = args = null;
    };
    return function() {
      var now = _.now();
      if (!previous && options.leading === false) previous = now;
      var remaining = wait - (now - previous);
      context = this;
      args = arguments;
      if (remaining <= 0 || remaining > wait) {
        if (timeout) {
          clearTimeout(timeout);
          timeout = null;
        }
        previous = now;
        result = func.apply(context, args);
        if (!timeout) context = args = null;
      } else if (!timeout && options.trailing !== false) {
        timeout = setTimeout(later, remaining);
      }
      return result;
    };
  };

一度目の関数が実行された時刻をpreviousに代入し、クロージャーに渡している。 二回目以降、関数が呼ばれるたびに、残りの時間を設定したsetTimeoutを発行する。

参考

jashkenas/underscore