-
-
Save nmsdvid/8807205 to your computer and use it in GitHub Desktop.
// Returns a function, that, as long as it continues to be invoked, will not | |
// be triggered. The function will be called after it stops being called for | |
// N milliseconds. If `immediate` is passed, trigger the function on the | |
// leading edge, instead of the trailing. | |
function debounce(func, wait, immediate) { | |
var timeout; | |
return function() { | |
var context = this, args = arguments; | |
clearTimeout(timeout); | |
timeout = setTimeout(function() { | |
timeout = null; | |
if (!immediate) func.apply(context, args); | |
}, wait); | |
if (immediate && !timeout) func.apply(context, args); | |
}; | |
} | |
/* minified */ | |
function debounce(a,b,c){var d;return function(){var e=this,f=arguments;clearTimeout(d),d=setTimeout(function(){d=null,c||a.apply(e,f)},b),c&&!d&&a.apply(e,f)}} | |
/* usage */ | |
var myEfficientFn = debounce(function() { | |
// All the taxing stuff you do | |
}, 250); | |
window.addEventListener('resize', myEfficientFn); |
eduardomoroni
commented
Aug 5, 2020
If found that, when setting
immediate
totrue
the debounced function was not invoked at all.
This is because as soon as you get atif (immediate && !timeout)
thetimeout
variable was just set.
Maybe move that if statement to before settingtimeout
?
This 👆
My TypeScript solution:
function debounce(func: (...args: unknown[]) => unknown, delay = 200) {
let timeout: number;
return function (...args: unknown[]) {
clearTimeout(timeout);
timeout = setTimeout(() => func(...args), delay);
};
}
or maybe (also when running in node or web)
function debounce<T>(func: (...args: T[]) => unknown, delay = 200) {
let timeout: number | NodeJS.Timeout;
return function (...args: T[]) {
clearTimeout(timeout as number);
timeout = setTimeout(() => func(...args), delay);
};
}
I suggest adding to our debounce
function return type unknown
or I prefer typeof func
as shown on line 4 below:
function debounce<T>(
func: (...args: T[]) => unknown,
delay = 200
): typeof func {
let timeout: number | NodeJS.Timeout;
return function (...args: T[]) {
clearTimeout(timeout as number);
timeout = setTimeout(() => func(...args), delay);
};
}
Without it results may be faced with type conversion issues a la ts(2352).
As indicated above, in the main gist function, using immediate
will break the implementation
So, for such needs where we wanted to call the function immediately (leading edge instead of trailing)
Try this implementation https://youmightnotneed.com/lodash#function