I have two quantity selector buttons.
After the user clicks in any of these buttons (increasing or decreasing quantity), I need to run a function.
But the user can click several times in a row, and I want to execute the function only once.
Like, wait 1 second after each click to run the function. If within this 1 second the user clicks the button again, reset the timer and wait for another second to run the function. When the user doesn´t click again within 1 second, run the function.
What´s the best way to do that in vanilla javascript?
CodePudding user response:
You just need to start a 1 second timer and reset it whenever the button click happens.
let timer
function handleClick() {
clearTimeout(timer)
timer = setTimeout(doSomething, 1000);
}
function doSomething() {
let div = document.getElementById("list")
let p = document.createElement("p")
p.textContent = "1 second passed without a click"
div.append(p)
}
<!DOCTYPE html>
<html>
<body>
<button onclick="handleClick()">Click me</button>
<div id=list></div>
</body>
</html>
CodePudding user response:
I see two solutions:
- If each click triggers some request, then disable button until the request is completed
- Use throttling for the function invoke. You can use RxJS's throttle or you can write your own throttle method.
https://medium.com/nerd-for-tech/debouncing-throttling-in-javascript-d36ace200cea
CodePudding user response:
You described a classic debounce
technique. Here is an implementation:
Taken from https://github.com/you-dont-need/You-Dont-Need-Lodash-Underscore#_debounce
Another way is to dig into Lodash source codes and copy it from there
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);
};
}
// Avoid costly calculations while the window size is in flux.
jQuery(window).on('resize', debounce(calculateLayout, 150));
Here is a nice article and a playground about it https://css-tricks.com/debouncing-throttling-explained-examples/
CodePudding user response:
You can try this in Vanilla JS :
const btn = document.querySelector('#btn');
const callback = event => {
console.log(event);
clearInterval(interval);
}
let interval;
btn.addEventListener('click', event => {
clearInterval(interval);
interval = setInterval( () => callback(event), 1000);
});
And the HTML :
<html>
<body>
<button id="btn">test</button>
</body>
</html>
That way you can pass the event instance to your callback.