mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-12 03:47:50 +00:00
Add maxWait option to _.debounce and implement _.throttle by way of _.debounce. [closes #285]
Former-commit-id: 63b41aac298e5fa89f7922e84b2ed0d5c6545bd3
This commit is contained in:
7
build.js
7
build.js
@@ -167,7 +167,7 @@
|
|||||||
'sortedIndex': ['createCallback', 'identity'],
|
'sortedIndex': ['createCallback', 'identity'],
|
||||||
'tap': ['value'],
|
'tap': ['value'],
|
||||||
'template': ['defaults', 'escape', 'escapeStringChar', 'keys', 'values'],
|
'template': ['defaults', 'escape', 'escapeStringChar', 'keys', 'values'],
|
||||||
'throttle': ['isObject'],
|
'throttle': ['debounce'],
|
||||||
'times': ['createCallback'],
|
'times': ['createCallback'],
|
||||||
'toArray': ['isString', 'slice', 'values'],
|
'toArray': ['isString', 'slice', 'values'],
|
||||||
'transform': ['createCallback', 'createObject', 'forOwn', 'isArray'],
|
'transform': ['createCallback', 'createObject', 'forOwn', 'isArray'],
|
||||||
@@ -3342,6 +3342,11 @@
|
|||||||
// remove `templateSettings` assignment
|
// remove `templateSettings` assignment
|
||||||
source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *lodash\.templateSettings[\s\S]+?};\n/, '');
|
source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *lodash\.templateSettings[\s\S]+?};\n/, '');
|
||||||
}
|
}
|
||||||
|
if (isRemoved(source, 'throttle')) {
|
||||||
|
_.each(['leading', 'maxWait', 'trailing'], function(prop) {
|
||||||
|
source = removeFromGetObject(source, prop);
|
||||||
|
});
|
||||||
|
}
|
||||||
if (isRemoved(source, 'value')) {
|
if (isRemoved(source, 'value')) {
|
||||||
source = removeFunction(source, 'chain');
|
source = removeFunction(source, 'chain');
|
||||||
source = removeFunction(source, 'wrapperToString');
|
source = removeFunction(source, 'wrapperToString');
|
||||||
|
|||||||
@@ -176,6 +176,7 @@
|
|||||||
'leading',
|
'leading',
|
||||||
'map',
|
'map',
|
||||||
'max',
|
'max',
|
||||||
|
'maxWait',
|
||||||
'memoize',
|
'memoize',
|
||||||
'merge',
|
'merge',
|
||||||
'methods',
|
'methods',
|
||||||
|
|||||||
112
lodash.js
112
lodash.js
@@ -324,27 +324,30 @@
|
|||||||
*/
|
*/
|
||||||
function getObject() {
|
function getObject() {
|
||||||
return objectPool.pop() || {
|
return objectPool.pop() || {
|
||||||
'args': null,
|
'args': '',
|
||||||
'array': null,
|
'array': null,
|
||||||
'bottom': null,
|
'bottom': '',
|
||||||
'criteria': null,
|
'criteria': null,
|
||||||
'false': null,
|
'false': false,
|
||||||
'firstArg': null,
|
'firstArg': '',
|
||||||
'index': null,
|
'index': 0,
|
||||||
'init': null,
|
'init': '',
|
||||||
'loop': null,
|
'leading': false,
|
||||||
'null': null,
|
'loop': '',
|
||||||
|
'maxWait': 0,
|
||||||
|
'null': false,
|
||||||
'number': null,
|
'number': null,
|
||||||
'object': null,
|
'object': null,
|
||||||
'push': null,
|
'push': null,
|
||||||
'shadowedProps': null,
|
'shadowedProps': null,
|
||||||
'string': null,
|
'string': null,
|
||||||
'support': null,
|
'support': null,
|
||||||
'top': null,
|
'top': '',
|
||||||
'true': null,
|
'trailing': false,
|
||||||
'undefined': null,
|
'true': false,
|
||||||
'useHas': null,
|
'undefined': false,
|
||||||
'useKeys': null,
|
'useHas': false,
|
||||||
|
'useKeys': false,
|
||||||
'value': null
|
'value': null
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -4810,6 +4813,7 @@
|
|||||||
* @param {Number} wait The number of milliseconds to delay.
|
* @param {Number} wait The number of milliseconds to delay.
|
||||||
* @param {Object} options The options object.
|
* @param {Object} options The options object.
|
||||||
* [leading=false] A boolean to specify execution on the leading edge of the timeout.
|
* [leading=false] A boolean to specify execution on the leading edge of the timeout.
|
||||||
|
* [maxWait] The maximum time `func` is allowed to be delayed before it's called.
|
||||||
* [trailing=true] A boolean to specify execution on the trailing 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
|
||||||
@@ -4827,35 +4831,67 @@
|
|||||||
result,
|
result,
|
||||||
thisArg,
|
thisArg,
|
||||||
callCount = 0,
|
callCount = 0,
|
||||||
|
lastCalled = 0,
|
||||||
|
maxWait = false,
|
||||||
|
maxTimeoutId = null,
|
||||||
timeoutId = null,
|
timeoutId = null,
|
||||||
trailing = true;
|
trailing = true;
|
||||||
|
|
||||||
function delayed() {
|
function trailingCall() {
|
||||||
var isCalled = trailing && (!leading || callCount > 1);
|
var isCalled = trailing && (!leading || callCount > 1);
|
||||||
callCount = timeoutId = 0;
|
callCount = 0;
|
||||||
|
|
||||||
|
clearTimeout(maxTimeoutId);
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
maxTimeoutId = timeoutId = null;
|
||||||
|
|
||||||
if (isCalled) {
|
if (isCalled) {
|
||||||
|
lastCalled = new Date;
|
||||||
result = func.apply(thisArg, args);
|
result = func.apply(thisArg, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
wait = nativeMax(0, wait || 0);
|
||||||
if (options === true) {
|
if (options === true) {
|
||||||
var leading = true;
|
var leading = true;
|
||||||
trailing = false;
|
trailing = false;
|
||||||
} else if (isObject(options)) {
|
} else if (isObject(options)) {
|
||||||
|
maxWait = 'maxWait' in options && nativeMax(wait, options.maxWait || 0);
|
||||||
leading = options.leading;
|
leading = options.leading;
|
||||||
trailing = 'trailing' in options ? options.trailing : trailing;
|
trailing = 'trailing' in options ? options.trailing : trailing;
|
||||||
}
|
}
|
||||||
return function() {
|
return function() {
|
||||||
|
var now = new Date;
|
||||||
|
if (!timeoutId && !leading) {
|
||||||
|
lastCalled = now;
|
||||||
|
}
|
||||||
|
var remaining = (maxWait || wait) - (now - lastCalled);
|
||||||
args = arguments;
|
args = arguments;
|
||||||
thisArg = this;
|
thisArg = this;
|
||||||
|
callCount++;
|
||||||
|
|
||||||
// avoid issues with Titanium and `undefined` timeout ids
|
// avoid issues with Titanium and `undefined` timeout ids
|
||||||
// https://github.com/appcelerator/titanium_mobile/blob/3_1_0_GA/android/titanium/src/java/ti/modules/titanium/TitaniumModule.java#L185-L192
|
// https://github.com/appcelerator/titanium_mobile/blob/3_1_0_GA/android/titanium/src/java/ti/modules/titanium/TitaniumModule.java#L185-L192
|
||||||
clearTimeout(timeoutId);
|
clearTimeout(timeoutId);
|
||||||
|
timeoutId = null;
|
||||||
|
|
||||||
if (leading && ++callCount < 2) {
|
if (maxWait === false) {
|
||||||
result = func.apply(thisArg, args);
|
if (leading && callCount < 2) {
|
||||||
|
result = func.apply(thisArg, args);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (remaining <= 0) {
|
||||||
|
clearTimeout(maxTimeoutId);
|
||||||
|
maxTimeoutId = null;
|
||||||
|
lastCalled = now;
|
||||||
|
result = func.apply(thisArg, args);
|
||||||
|
}
|
||||||
|
else if (!maxTimeoutId) {
|
||||||
|
maxTimeoutId = setTimeout(trailingCall, remaining);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (wait !== maxWait) {
|
||||||
|
timeoutId = setTimeout(trailingCall, wait);
|
||||||
}
|
}
|
||||||
timeoutId = setTimeout(delayed, wait);
|
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -5056,47 +5092,23 @@
|
|||||||
* }));
|
* }));
|
||||||
*/
|
*/
|
||||||
function throttle(func, wait, options) {
|
function throttle(func, wait, options) {
|
||||||
var args,
|
var leading = true,
|
||||||
result,
|
|
||||||
thisArg,
|
|
||||||
lastCalled = 0,
|
|
||||||
leading = true,
|
|
||||||
timeoutId = null,
|
|
||||||
trailing = true;
|
trailing = true;
|
||||||
|
|
||||||
function trailingCall() {
|
|
||||||
timeoutId = null;
|
|
||||||
if (trailing) {
|
|
||||||
lastCalled = new Date;
|
|
||||||
result = func.apply(thisArg, args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (options === false) {
|
if (options === false) {
|
||||||
leading = false;
|
leading = false;
|
||||||
} else if (isObject(options)) {
|
} else if (isObject(options)) {
|
||||||
leading = 'leading' in options ? options.leading : leading;
|
leading = 'leading' in options ? options.leading : leading;
|
||||||
trailing = 'trailing' in options ? options.trailing : trailing;
|
trailing = 'trailing' in options ? options.trailing : trailing;
|
||||||
}
|
}
|
||||||
return function() {
|
options = getObject();
|
||||||
var now = new Date;
|
options.leading = leading;
|
||||||
if (!timeoutId && !leading) {
|
options.maxWait = wait;
|
||||||
lastCalled = now;
|
options.trailing = trailing;
|
||||||
}
|
|
||||||
var remaining = wait - (now - lastCalled);
|
|
||||||
args = arguments;
|
|
||||||
thisArg = this;
|
|
||||||
|
|
||||||
if (remaining <= 0) {
|
var result = debounce(func, wait, options);
|
||||||
clearTimeout(timeoutId);
|
releaseObject(options);
|
||||||
timeoutId = null;
|
return result;
|
||||||
lastCalled = now;
|
|
||||||
result = func.apply(thisArg, args);
|
|
||||||
}
|
|
||||||
else if (!timeoutId) {
|
|
||||||
timeoutId = setTimeout(trailingCall, remaining);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
28
test/test.js
28
test/test.js
@@ -634,6 +634,34 @@
|
|||||||
QUnit.start();
|
QUnit.start();
|
||||||
}, 64);
|
}, 64);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
asyncTest('should work with `maxWait` option', function() {
|
||||||
|
var limit = 96,
|
||||||
|
withCount = 0,
|
||||||
|
withoutCount = 0;
|
||||||
|
|
||||||
|
var withMaxWait = _.debounce(function() {
|
||||||
|
withCount++;
|
||||||
|
}, 32, { 'maxWait': 64 });
|
||||||
|
|
||||||
|
var withoutMaxWait = _.debounce(function() {
|
||||||
|
withoutCount++;
|
||||||
|
}, 32);
|
||||||
|
|
||||||
|
var start = new Date;
|
||||||
|
while ((new Date - start) < limit) {
|
||||||
|
withMaxWait();
|
||||||
|
withoutMaxWait();
|
||||||
|
}
|
||||||
|
strictEqual(withCount, 1);
|
||||||
|
strictEqual(withoutCount, 0);
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
strictEqual(withCount, 2);
|
||||||
|
strictEqual(withoutCount, 1);
|
||||||
|
QUnit.start();
|
||||||
|
}, 64);
|
||||||
|
});
|
||||||
}());
|
}());
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|||||||
Reference in New Issue
Block a user