If I have a function foo
. It receives many calls at a short period of time.
function foo(name) {
console.log(`Hi ${name}, it is now: `, new Date());
}
Delaying consecutive function invocations (debouncing ) is working fine using lodash .
const debouncedFoo = _.debounce(foo, 1000 );
However, my target is to NOT execute this whole fleet of invocations even the timeout (1000
) have elapsed, and consider only the last invocation to be executed .
In other words, if i called debouncedFoo
5 times within 900 ms (which is less than "wait param" 1000ms ), I want foo
to be executed only once which is the last (5ᵗʰ) call .
Reading lodash documentation , I understood that debounce
is overloaded by 3ʳᵈ argument which is options. I used them and the expected behavior does not happen:
// first attempt
const debouncedFoo = _.debounce(foo, 1000, {leading: true} );
// second attempt
const debouncedFoo = _.debounce(foo, 1000, {trailing: false} );
It's simple. They do the exact same thing (rate limiting) except while throttle is being called it'll fire your function periodically, while debounce only fires once at the end. Example: If you're scrolling, throttle will slowly call your function while you scroll (every X milliseconds).
The Lodash debounce function returns a debounced function that when called will execute a function after X milliseconds pass since its last execution.
The easiest way to allow to cancel an already called function within its debounce period is to call it from a cancelable wrap. Really just add 3 lines of code and an optional condition. You cancel it by calling it again with abort = true .
The debounce() function forces a function to wait a certain amount of time before running again. The function is built to limit the number of times a function is called. The Send Request() function is debounced. Requests are sent only after fixed time intervals regardless of how many times the user presses the button.
Not familiar with lodash, but you can implement that behavior easily:
function debounce(cb, duration) {
let timer;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => {
cb(...args);
}, duration);
};
}
function debounce(cb, duration) {
var timer;
return function() {
var args = arguments;
clearTimeout(timer);
timer = setTimeout(function() {
cb.apply(null, args);
}, duration);
};
}
var call = debounce(console.log.bind(console), 1000);
setTimeout(function(){ call(200); }, 200);
setTimeout(function(){ call(400); }, 400);
setTimeout(function(){ call(600); }, 600);
setTimeout(function(){ call(800); }, 800);
setTimeout(function(){ call(900); }, 900);
Like @AndyO mentioned, make sure you're not re-creating the debounced function upon every state change.
I had the same problem, so I used useCallback
to solve it.
import React, { useCallback } from 'React';
import { debounce } from 'lodash';
const myFunction = () => { // some logic };
const debouncedMyFunction = useCallback(debounce(myFunction, 300), []);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With