From 367f0bd6a943078ea4f14e32c2415cf95be3aa4d Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Tue, 1 May 2012 21:11:40 -0400 Subject: [PATCH] lodash: Optimize and simplify `throttle`. [cowboy, jddalton] Former-commit-id: 52e19aeb8671e86a13bf54876bf1f3f1b4644437 --- lodash.js | 40 +++++++++++++++++++++------------------- test/test.js | 25 +++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 19 deletions(-) diff --git a/lodash.js b/lodash.js index d60d59d8c..bf9909ece 100644 --- a/lodash.js +++ b/lodash.js @@ -1701,8 +1701,10 @@ } /** - * Creates a new function that, when executed, will only call the original - * function at most once per every `wait` milliseconds. + * Creates a new function that, when executed, will only call the `func` + * function at most once per every `wait` milliseconds. If the throttled function + * is invoked more than once, `func` will also be called on the trailing edge + * of the `wait` timeout. * * @static * @memberOf _ @@ -1716,32 +1718,32 @@ * jQuery(window).on('scroll', throttled); */ function throttle(func, wait) { - var args, more, thisArg, throttling, timeout, - whenDone = debounce(function() { more = throttling = false; }, wait); + var args, + result, + thisArg, + timeoutId, + lastCalled = 0; - function delayed() { - timeout = undefined; - if (more) { - func.apply(thisArg, args); - } - whenDone(); + function trailingCall() { + lastCalled = new Date; + timeoutId = undefined; + func.apply(thisArg, args); } return function() { - var result; + var now = new Date, + remain = wait - (now - lastCalled); + args = arguments; thisArg = this; - if (!timeout) { - timeout = setTimeout(delayed, wait); - } - if (throttling) { - more = true; - } else { - throttling = true; + if (remain <= 0) { + lastCalled = now; result = func.apply(thisArg, args); } - whenDone(); + else if (!timeoutId) { + timeoutId = setTimeout(trailingCall, remain); + } return result; }; } diff --git a/test/test.js b/test/test.js index 77ffa7a08..047b85e84 100644 --- a/test/test.js +++ b/test/test.js @@ -187,6 +187,31 @@ /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.throttle'); + + (function() { + test('subsequent calls should return the result of the first call', function() { + var throttled = _.throttle(function(value) { return value; }, 100), + result = [throttled('x'), throttled('y')]; + + deepEqual(result, ['x', 'x']); + }); + + test('supports calls in a loop', function() { + var counter = 0, + throttled = _.throttle(function() { counter++; }, 100), + start = new Date, + limit = 220; + + while ((new Date - start) < limit) { + throttled(); + } + equal(counter, 3); + }); + }()); + + /*--------------------------------------------------------------------------*/ + QUnit.module('lodash.toArray'); (function() {