Add an options object argument to _.debounce and _.throttle. [closes #222]

Former-commit-id: d5eb3bc21d4a5c6d25314153f98d43a3d11eb4fa
This commit is contained in:
John-David Dalton
2013-04-04 08:52:42 -07:00
parent 3cfe7c9a56
commit 6fe322da27
2 changed files with 50 additions and 21 deletions

View File

@@ -156,6 +156,7 @@
'keys', 'keys',
'last', 'last',
'lastIndexOf', 'lastIndexOf',
'leading',
'map', 'map',
'max', 'max',
'memoize', 'memoize',
@@ -204,6 +205,7 @@
'throttle', 'throttle',
'times', 'times',
'toArray', 'toArray',
'trailing',
'unescape', 'unescape',
'unindexedChars', 'unindexedChars',
'union', 'union',

View File

@@ -4440,44 +4440,53 @@
/** /**
* Creates a function that will delay the execution of `func` until after * Creates a function that will delay the execution of `func` until after
* `wait` milliseconds have elapsed since the last time it was invoked. Pass * `wait` milliseconds have elapsed since the last time it was invoked. Pass
* `true` for `immediate` to cause debounce to invoke `func` on the leading, * an `options` object to indicate that `func` should be invoked on the leading
* instead of the trailing, edge of the `wait` timeout. Subsequent calls to * and/or trailing edge of the `wait` timeout. Subsequent calls to the debounced
* the debounced function will return the result of the last `func` call. * function will return the result of the last `func` call.
* *
* @static * @static
* @memberOf _ * @memberOf _
* @category Functions * @category Functions
* @param {Function} func The function to debounce. * @param {Function} func The function to debounce.
* @param {Number} wait The number of milliseconds to delay. * @param {Number} wait The number of milliseconds to delay.
* @param {Boolean} immediate A flag to indicate execution is on the leading * @param {Object} options The options object.
* edge of the timeout. * [leading=false] A boolean to specify execution on the leading edge of the timeout.
* [trailing=true] A boolean to specify execution on the trailing edge of the timeout.
* @returns {Function} Returns the new debounced function. * @returns {Function} Returns the new debounced function.
* @example * @example
* *
* var lazyLayout = _.debounce(calculateLayout, 300); * var lazyLayout = _.debounce(calculateLayout, 300);
* jQuery(window).on('resize', lazyLayout); * jQuery(window).on('resize', lazyLayout);
*/ */
function debounce(func, wait, immediate) { function debounce(func, wait, options) {
var args, var args,
result, result,
thisArg, thisArg,
timeoutId; timeoutId,
trailing = true;
function delayed() { function delayed() {
timeoutId = null; timeoutId = null;
if (!immediate) { if (trailing) {
result = func.apply(thisArg, args); result = func.apply(thisArg, args);
} }
} }
if (options === true) {
var leading = true;
trailing = false;
} else if (options) {
leading = options.leading;
trailing = options.trailing;
}
return function() { return function() {
var isImmediate = immediate && !timeoutId; var isLeading = leading && !timeoutId;
args = arguments; args = arguments;
thisArg = this; thisArg = this;
clearTimeout(timeoutId); clearTimeout(timeoutId);
timeoutId = setTimeout(delayed, wait); timeoutId = setTimeout(delayed, wait);
if (isImmediate) { if (isLeading) {
result = func.apply(thisArg, args); result = func.apply(thisArg, args);
} }
return result; return result;
@@ -4647,39 +4656,57 @@
} }
/** /**
* Creates a function that, when executed, will only call the `func` * Creates a function that, when executed, will only call the `func` function
* function at most once per every `wait` milliseconds. If the throttled * at most once per every `wait` milliseconds. If the throttled function is
* function is invoked more than once during the `wait` timeout, `func` will * invoked more than once during the `wait` timeout, `func` will also be called
* also be called on the trailing edge of the timeout. Subsequent calls to the * on the trailing edge of the timeout. Pass an `options` object to indicate
* throttled function will return the result of the last `func` call. * that `func` should be invoked on the leading and/or trailing edge of the
* `wait` timeout. Subsequent calls to the throttled function will return
* the result of the last `func` call.
* *
* @static * @static
* @memberOf _ * @memberOf _
* @category Functions * @category Functions
* @param {Function} func The function to throttle. * @param {Function} func The function to throttle.
* @param {Number} wait The number of milliseconds to throttle executions to. * @param {Number} wait The number of milliseconds to throttle executions to.
* @param {Object} options The options object.
* [leading=true] A boolean to specify execution on the leading edge of the timeout.
* [trailing=true] A boolean to specify execution on the trailing edge of the timeout.
* @returns {Function} Returns the new throttled function. * @returns {Function} Returns the new throttled function.
* @example * @example
* *
* var throttled = _.throttle(updatePosition, 100); * var throttled = _.throttle(updatePosition, 100);
* jQuery(window).on('scroll', throttled); * jQuery(window).on('scroll', throttled);
*/ */
function throttle(func, wait) { function throttle(func, wait, options) {
var args, var args,
result, result,
thisArg, thisArg,
timeoutId, timeoutId,
lastCalled = 0; lastCalled = 0,
leading = true,
trailing = true;
function trailingCall() { function trailingCall() {
lastCalled = new Date; lastCalled = new Date;
timeoutId = null; timeoutId = null;
result = func.apply(thisArg, args);
if (trailing) {
result = func.apply(thisArg, args);
}
}
if (options === false) {
leading = false;
} else if (options) {
leading = options.leading;
trailing = options.trailing;
} }
return function() { return function() {
var now = new Date, var now = new Date;
remaining = wait - (now - lastCalled); if (!timeoutId && !leading) {
lastCalled = now;
}
var remaining = wait - (now - lastCalled);
args = arguments; args = arguments;
thisArg = this; thisArg = this;