mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-01-31 23:37:49 +00:00
Add a cancel function to debounced functions. [closes #567]
This commit is contained in:
70
lodash.js
70
lodash.js
@@ -5363,6 +5363,7 @@
|
||||
/**
|
||||
* Creates a function that will delay the execution of `func` until after
|
||||
* `wait` milliseconds have elapsed since the last time it was invoked.
|
||||
* The created function comes with a `cancel` method to cancel delayed calls.
|
||||
* Provide an options object to indicate that `func` should be invoked on
|
||||
* the leading and/or trailing edge of the `wait` timeout. Subsequent calls
|
||||
* to the debounced function will return the result of the last `func` call.
|
||||
@@ -5384,8 +5385,7 @@
|
||||
* @example
|
||||
*
|
||||
* // avoid costly calculations while the window size is in flux
|
||||
* var lazyLayout = _.debounce(calculateLayout, 150);
|
||||
* jQuery(window).on('resize', lazyLayout);
|
||||
* jQuery(window).on('resize', _.debounce(calculateLayout, 150));
|
||||
*
|
||||
* // execute `sendMail` when the click event is fired, debouncing subsequent calls
|
||||
* jQuery('#postbox').on('click', _.debounce(sendMail, 300, {
|
||||
@@ -5395,9 +5395,26 @@
|
||||
*
|
||||
* // ensure `batchLog` is executed once after 1 second of debounced calls
|
||||
* var source = new EventSource('/stream');
|
||||
* source.addEventListener('message', _.debounce(batchLog, 250, {
|
||||
* jQuery(source).on('message', _.debounce(batchLog, 250, {
|
||||
* 'maxWait': 1000
|
||||
* }, false);
|
||||
*
|
||||
* // cancelling a debounced call
|
||||
* var todoChanges = _.debounce(batchLog, 1000);
|
||||
* Object.observe(models.todo, todoChanges);
|
||||
*
|
||||
* Object.observe(models, function(changes) {
|
||||
* if (_.find(changes, { 'name': 'todo', 'type': 'delete'})) {
|
||||
* todoChanges.cancel();
|
||||
* }
|
||||
* }, ['delete']);
|
||||
*
|
||||
* // ...at some point `models.todo` is changed
|
||||
* models.todo.completed = true;
|
||||
*
|
||||
* // ...before 1 second has passed `models.todo` is deleted
|
||||
* // which cancels the debounced `todoChanges` call
|
||||
* delete models.todo;
|
||||
*/
|
||||
function debounce(func, wait, options) {
|
||||
var args,
|
||||
@@ -5423,7 +5440,18 @@
|
||||
maxWait = 'maxWait' in options && nativeMax(wait, +options.maxWait || 0);
|
||||
trailing = 'trailing' in options ? options.trailing : trailing;
|
||||
}
|
||||
var delayed = function() {
|
||||
|
||||
function cancel() {
|
||||
if (timeoutId) {
|
||||
clearTimeout(timeoutId);
|
||||
}
|
||||
if (maxTimeoutId) {
|
||||
clearTimeout(maxTimeoutId);
|
||||
}
|
||||
maxTimeoutId = timeoutId = trailingCall = undefined;
|
||||
}
|
||||
|
||||
function delayed() {
|
||||
var remaining = wait - (now() - stamp);
|
||||
if (remaining <= 0 || remaining > wait) {
|
||||
if (maxTimeoutId) {
|
||||
@@ -5441,9 +5469,9 @@
|
||||
} else {
|
||||
timeoutId = setTimeout(delayed, remaining);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var maxDelayed = function() {
|
||||
function maxDelayed() {
|
||||
if (timeoutId) {
|
||||
clearTimeout(timeoutId);
|
||||
}
|
||||
@@ -5455,9 +5483,9 @@
|
||||
args = thisArg = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return function() {
|
||||
function debounced() {
|
||||
args = arguments;
|
||||
stamp = now();
|
||||
thisArg = this;
|
||||
@@ -5497,7 +5525,9 @@
|
||||
args = thisArg = null;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
}
|
||||
debounced.cancel = cancel;
|
||||
return debounced;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -5732,11 +5762,12 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a function that, when executed, will only call the `func` function
|
||||
* at most once per every `wait` milliseconds. Provide an options object to
|
||||
* indicate 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.
|
||||
* Creates a function that will only call the `func` function at most once
|
||||
* per every `wait` milliseconds. The created function comes with a `cancel`
|
||||
* method to cancel delayed calls. Provide an options object to indicate 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.
|
||||
*
|
||||
* Note: If `leading` and `trailing` options are `true`, `func` will be called
|
||||
* on the trailing edge of the timeout only if the the throttled function is
|
||||
@@ -5754,13 +5785,14 @@
|
||||
* @example
|
||||
*
|
||||
* // avoid excessively updating the position while scrolling
|
||||
* var throttled = _.throttle(updatePosition, 100);
|
||||
* jQuery(window).on('scroll', throttled);
|
||||
* jQuery(window).on('scroll', _.throttle(updatePosition, 100));
|
||||
*
|
||||
* // execute `renewToken` when the click event is fired, but not more than once every 5 minutes
|
||||
* jQuery('.interactive').on('click', _.throttle(renewToken, 300000, {
|
||||
* 'trailing': false
|
||||
* }));
|
||||
* var throttled = _.throttle(renewToken, 300000, { 'trailing': false })
|
||||
* jQuery('.interactive').on('click',);
|
||||
*
|
||||
* // cancelling a trailing throttled call
|
||||
* jQuery(window).on('popstate', throttled.cancel);
|
||||
*/
|
||||
function throttle(func, wait, options) {
|
||||
var leading = true,
|
||||
|
||||
22
test/test.js
22
test/test.js
@@ -9412,6 +9412,28 @@
|
||||
QUnit.start();
|
||||
}
|
||||
});
|
||||
|
||||
asyncTest('_.' + methodName + ' should support cancelling delayed calls', 1, function() {
|
||||
if (!(isRhino && isModularize)) {
|
||||
var callCount = 0;
|
||||
|
||||
var funced = func(function() {
|
||||
callCount++;
|
||||
}, 32, { 'leading': false });
|
||||
|
||||
funced();
|
||||
funced.cancel();
|
||||
|
||||
setTimeout(function() {
|
||||
strictEqual(callCount, 0);
|
||||
QUnit.start();
|
||||
}, 64);
|
||||
}
|
||||
else {
|
||||
skipTest();
|
||||
QUnit.start();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
Reference in New Issue
Block a user