diff --git a/test/functions.js b/test/functions.js index fa74f26ea..05155eca9 100644 --- a/test/functions.js +++ b/test/functions.js @@ -90,7 +90,7 @@ $(document).ready(function() { _.delay(function(){ ok(deferred, "deferred the function"); start(); }, 50); }); - asyncTest("functions: throttle", 2, function() { + asyncTest("functions: throttle", 1, function() { var counter = 0; var incr = function(){ counter++; }; var throttledIncr = _.throttle(incr, 100); @@ -99,7 +99,6 @@ $(document).ready(function() { setTimeout(throttledIncr, 140); setTimeout(throttledIncr, 220); setTimeout(throttledIncr, 240); - _.delay(function(){ ok(counter == 1, "incr throttle was called immediately"); }, 40); _.delay(function(){ ok(counter == 3, "incr was throttled"); start(); }, 400); }); diff --git a/underscore.js b/underscore.js index d5279f4b6..72237d180 100644 --- a/underscore.js +++ b/underscore.js @@ -520,23 +520,8 @@ return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1))); }; - // Returns a function, that, when invoked, will only be triggered at most once - // during a given window of time. - _.throttle = function(func, wait) { - var ran = false; - return function() { - if (!ran) { - ran = true; - setTimeout(function(){ ran = false; }, wait); - return func.apply(this, arguments); - } - }; - }; - - // Returns a function, that, as long as it continues to be invoked, will not - // be triggered. The function will be called after it stops being called for - // N milliseconds. - _.debounce = function(func, wait) { + // Internal function used to implement `_.throttle` and `_.debounce`. + var limit = function(func, wait, debounce) { var timeout; return function() { var context = this, args = arguments; @@ -544,11 +529,24 @@ timeout = null; func.apply(context, args); }; - if (timeout) clearTimeout(timeout); - timeout = setTimeout(throttler, wait); + if (debounce) clearTimeout(timeout); + if (debounce || !timeout) timeout = setTimeout(throttler, wait); }; }; + // Returns a function, that, when invoked, will only be triggered at most once + // during a given window of time. + _.throttle = function(func, wait) { + return limit(func, wait, false); + }; + + // Returns a function, that, as long as it continues to be invoked, will not + // be triggered. The function will be called after it stops being called for + // N milliseconds. + _.debounce = function(func, wait) { + return limit(func, wait, true); + }; + // Returns a function that will be executed at most one time, no matter how // often you call it. Useful for lazy initialization. _.once = function(func) {