mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-08 02:17:48 +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
|
* Creates a function that will delay the execution of `func` until after
|
||||||
* `wait` milliseconds have elapsed since the last time it was invoked.
|
* `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
|
* Provide an options object to indicate that `func` should be invoked on
|
||||||
* the leading and/or trailing edge of the `wait` timeout. Subsequent calls
|
* 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.
|
* to the debounced function will return the result of the last `func` call.
|
||||||
@@ -5384,8 +5385,7 @@
|
|||||||
* @example
|
* @example
|
||||||
*
|
*
|
||||||
* // avoid costly calculations while the window size is in flux
|
* // avoid costly calculations while the window size is in flux
|
||||||
* var lazyLayout = _.debounce(calculateLayout, 150);
|
* jQuery(window).on('resize', _.debounce(calculateLayout, 150));
|
||||||
* jQuery(window).on('resize', lazyLayout);
|
|
||||||
*
|
*
|
||||||
* // execute `sendMail` when the click event is fired, debouncing subsequent calls
|
* // execute `sendMail` when the click event is fired, debouncing subsequent calls
|
||||||
* jQuery('#postbox').on('click', _.debounce(sendMail, 300, {
|
* jQuery('#postbox').on('click', _.debounce(sendMail, 300, {
|
||||||
@@ -5395,9 +5395,26 @@
|
|||||||
*
|
*
|
||||||
* // ensure `batchLog` is executed once after 1 second of debounced calls
|
* // ensure `batchLog` is executed once after 1 second of debounced calls
|
||||||
* var source = new EventSource('/stream');
|
* var source = new EventSource('/stream');
|
||||||
* source.addEventListener('message', _.debounce(batchLog, 250, {
|
* jQuery(source).on('message', _.debounce(batchLog, 250, {
|
||||||
* 'maxWait': 1000
|
* 'maxWait': 1000
|
||||||
* }, false);
|
* }, 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) {
|
function debounce(func, wait, options) {
|
||||||
var args,
|
var args,
|
||||||
@@ -5423,7 +5440,18 @@
|
|||||||
maxWait = 'maxWait' in options && nativeMax(wait, +options.maxWait || 0);
|
maxWait = 'maxWait' in options && nativeMax(wait, +options.maxWait || 0);
|
||||||
trailing = 'trailing' in options ? options.trailing : trailing;
|
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);
|
var remaining = wait - (now() - stamp);
|
||||||
if (remaining <= 0 || remaining > wait) {
|
if (remaining <= 0 || remaining > wait) {
|
||||||
if (maxTimeoutId) {
|
if (maxTimeoutId) {
|
||||||
@@ -5441,9 +5469,9 @@
|
|||||||
} else {
|
} else {
|
||||||
timeoutId = setTimeout(delayed, remaining);
|
timeoutId = setTimeout(delayed, remaining);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
var maxDelayed = function() {
|
function maxDelayed() {
|
||||||
if (timeoutId) {
|
if (timeoutId) {
|
||||||
clearTimeout(timeoutId);
|
clearTimeout(timeoutId);
|
||||||
}
|
}
|
||||||
@@ -5455,9 +5483,9 @@
|
|||||||
args = thisArg = null;
|
args = thisArg = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
return function() {
|
function debounced() {
|
||||||
args = arguments;
|
args = arguments;
|
||||||
stamp = now();
|
stamp = now();
|
||||||
thisArg = this;
|
thisArg = this;
|
||||||
@@ -5497,7 +5525,9 @@
|
|||||||
args = thisArg = null;
|
args = thisArg = null;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
};
|
}
|
||||||
|
debounced.cancel = cancel;
|
||||||
|
return debounced;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -5732,11 +5762,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a function that, when executed, will only call the `func` function
|
* Creates a function that will only call the `func` function at most once
|
||||||
* at most once per every `wait` milliseconds. Provide an options object to
|
* per every `wait` milliseconds. The created function comes with a `cancel`
|
||||||
* indicate that `func` should be invoked on the leading and/or trailing edge
|
* method to cancel delayed calls. Provide an options object to indicate that
|
||||||
* of the `wait` timeout. Subsequent calls to the throttled function will
|
* `func` should be invoked on the leading and/or trailing edge of the `wait`
|
||||||
* return the result of the last `func` call.
|
* 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
|
* 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
|
* on the trailing edge of the timeout only if the the throttled function is
|
||||||
@@ -5754,13 +5785,14 @@
|
|||||||
* @example
|
* @example
|
||||||
*
|
*
|
||||||
* // avoid excessively updating the position while scrolling
|
* // avoid excessively updating the position while scrolling
|
||||||
* var throttled = _.throttle(updatePosition, 100);
|
* jQuery(window).on('scroll', _.throttle(updatePosition, 100));
|
||||||
* jQuery(window).on('scroll', throttled);
|
|
||||||
*
|
*
|
||||||
* // execute `renewToken` when the click event is fired, but not more than once every 5 minutes
|
* // execute `renewToken` when the click event is fired, but not more than once every 5 minutes
|
||||||
* jQuery('.interactive').on('click', _.throttle(renewToken, 300000, {
|
* var throttled = _.throttle(renewToken, 300000, { 'trailing': false })
|
||||||
* 'trailing': false
|
* jQuery('.interactive').on('click',);
|
||||||
* }));
|
*
|
||||||
|
* // cancelling a trailing throttled call
|
||||||
|
* jQuery(window).on('popstate', throttled.cancel);
|
||||||
*/
|
*/
|
||||||
function throttle(func, wait, options) {
|
function throttle(func, wait, options) {
|
||||||
var leading = true,
|
var leading = true,
|
||||||
|
|||||||
22
test/test.js
22
test/test.js
@@ -9412,6 +9412,28 @@
|
|||||||
QUnit.start();
|
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