From bceb77e325839277b2a03b34d1247e7d555cd0ac Mon Sep 17 00:00:00 2001 From: Jeremy Ashkenas Date: Mon, 24 Oct 2011 12:05:59 -0400 Subject: [PATCH] Fixes #170, #266 ... throttle now starts at the beginning of the call. --- test/functions.js | 3 ++- underscore.js | 36 +++++++++++++++++++----------------- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/test/functions.js b/test/functions.js index 05155eca9..fa74f26ea 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", 1, function() { + asyncTest("functions: throttle", 2, function() { var counter = 0; var incr = function(){ counter++; }; var throttledIncr = _.throttle(incr, 100); @@ -99,6 +99,7 @@ $(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 72237d180..d5279f4b6 100644 --- a/underscore.js +++ b/underscore.js @@ -520,8 +520,23 @@ return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1))); }; - // Internal function used to implement `_.throttle` and `_.debounce`. - var limit = function(func, wait, debounce) { + // 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) { var timeout; return function() { var context = this, args = arguments; @@ -529,24 +544,11 @@ timeout = null; func.apply(context, args); }; - if (debounce) clearTimeout(timeout); - if (debounce || !timeout) timeout = setTimeout(throttler, wait); + if (timeout) clearTimeout(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) {