Context: It's the first time I try to implement a debounce() function and probably I misunderstood something, because the function it's calling my API multiple times, although the delay it's been aplied, my code:
async updateSelectAll(value) {
const execute = this.debounce(async () => {
await this.getTotalDaeMunicipio(this.filtroDaeMunicipio);
await this.gerarGraficoMunicipio();
}, 1000);
execute();
},
debounce(func, wait) {
let timer = null;
return () => {
clearTimeout(timer);
timer = setTimeout(func, wait);
};
}
The function updateSelectAll it's called everytime the user clicks on a checkbox, this is working.
The problem: when the user clicks on the checkbox, the function updateSelectAll it's called, after 1 second(1000ms), the API is called through the function execute() which have the debounce function, but when the user click multiple times on the checkbox, the API is called multiple times.
Expected behavior: when the checkobox it's clicked multiple times, was meant to do just one call to the API.
You create a local variable timer in the debounce function that the inner function closes over and has access to.
debounce(func, wait) {
let timer = null;
return () => {
clearTimeout(timer);
timer = setTimeout(func, wait);
};
}
The problem is, though, that you invoke this.debounce() multiple times, which is not sharing this timer. You need to share this timer between invocations of debounce to achieve your goal
Related
Actually, Here I am going to call an API on the bases of a word which I want to search and the words which are stared from my searching words are searched properly but here the problem is the if i typed a big word like that length is more than 3 so the API hit's 3 times and also return the result related to those words but in this case I just want to override that API calls and run only last one API with the complete word which I typed so, Is there any way to handle this situation.
You can use a button for start searching
Also you can use onSubmitEditing to start calling the api after the user type a complete word . otherwise this is inevitable to handle this problem
I think you can use debounce function.It will delay your function call,and just call the recent one.
function debounce (fn, delay) {
let timer = null;
return function () {
let args = arguments;
let context = this;
if (timer) {
clearTimeout(timer);
timer = setTimeout(function () {
fn.apply(context, args);
}, delay);
} else {
timer = setTimeout(function () {
fn.apply(context, args);
}, delay);
}
}
}
function apiCall(){
// your code
}
function realCall(){
return debounce(apiCall,300)
}
In a JavaScript function, I have this code:
clicker1.addEventListener("click", nextImage, true);
The problem is that when the button with this event is clicked rapidly, it causes errors.
I need to make it so once the button is clicked there, is a delay where the click event doesn't run the function.
The pattern you are looking for is called throttling.
Here's an example implementation of a throttle function:
const throttle = (func, limit) => {
let lastFunc
let lastRan
return function() {
const context = this
const args = arguments
if (!lastRan) {
func.apply(context, args)
lastRan = Date.now()
} else {
clearTimeout(lastFunc)
lastFunc = setTimeout(function() {
if ((Date.now() - lastRan) >= limit) {
func.apply(context, args)
lastRan = Date.now()
}
}, limit - (Date.now() - lastRan))
}
}
}
The function gets the function to be throttled as an argument, along with a limit argument which is the interval in milliseconds until the next function call is permitted.
It returns another function which executes the provided function in the specified interval.
You use it like this:
clicker1.addEventListener("click", throttle(nextImage, 1000), true);
So now, if somebody "spam clicks" your clicker button, the nextImage function is only executed every second.
Note: If you use Lodash, you can use its own throttle implementation _.throttle.
How about disabling the button for a short while using setTimeout. In this example, the button is disabled for 2000 ms.
function myFunction() {
console.log('clicked !!');
document.getElementById("myButton").disabled = true;
setTimeout(function(){
document.getElementById("myButton").disabled = false;
},2000);
}
<button onClick="myFunction()" id="myButton">Press me</button>
I want to create a function that starts a timeout, but if the function is called again, before the timer ends, cancel the original call and start the timer again.
I thought I could do:
function setTimer() {
setTimeout(() => {
// do something
}, 3000)
}
...but that doesn't work, for every time I run setTimer(), it doesn't cancel the original call.
Can anyone point me in the right direction?
setTimeout returns an id you can use to clear that timeout with clearTimeout(). So you can clear the existing timeout at the beginning of your function.
For example if you keep clicking it will keep restarting -- if you don't click it finishes in 2 seconds:
let timerID;
function setTimer() {
console.log("starting/restarting timer")
clearTimeout(timerID)
timerID = setTimeout(() => {
console.log("finished")
}, 2000)
}
<p onclick="setTimer()">click to start</p>
What you want to do is cancel the existing timeout and start it over? You can do this by using cleartimeout
let timeoutFunctionVar = null;
const setTimeoutFunction = () => {
clearTimeout(timeoutFunctionVar)
timeoutFunctionVar = setTimeout(() => {
// do something
}, 3000)
};
setTimeoutFunction()
So every time setTimeoutFunction() gets called, the previous timeout gets reset
I figured this question gets asked frequently, especially for searches triggered by key events, but I couldn't find any.
The basic idea is that you keep the timeout id stateful, so you can clear it on subsequent invocations to the TO setter:
const MS_IN_SEC = 1000;
let old_timeout;
function TO_setter(searchString) {
if (old_timeout)
window.clearTimeout(old_timeout);
old_timeout = window.setTimeout(search, 2 * MS_IN_SEC, searchString);
}
function search(s) {
console.log('search for: %s', s);
}
Consider this C# question: Countdown timer increase on interaction?
I am in need of an equivalent for Javascript. That is, the following:
Problem
I need a callback to be called after some time T however if user interaction happens before the callback is executed then this time T must be increased by some number X. How is this modelled using Javascript?
Background (the why)
I have a page forward button which upon being clicked increases the page by 1. Increasing the page causes some hefty computations to happen so it'd be preferable to only switch page after some small time frame so that a user that's spamming the page button won't make the programs perf. go in the bin.
If I understand correctly, you can simply clear the timeout and set it again.
clearTimeout(timer);
timer = setTimeout(function(){}, 1000);
I made a quick codepen with an example. I hope it helps: https://codepen.io/daniti/pen/gjePdo
You can use a debounce function. It sets a timer and if an interation happens before timer expiration it deletes the old timer and creates a new one, effectively resets the time. Example:
function debounce(fn, delay) {
let timerId;
return function (...args) {
if (timerId)
clearTimeout(timerId);
timerId = setTimeout(() => {
fn(...args);
timerId = null;
}, delay);
}
}
You can use a timeout : https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout
document.getElementById("spamMe").onclick = doLongAction;
var canDoLongAction = true;
var timeout;
function doLongAction() {
if (canDoLongAction) {
// prevent relaunch of action
canDoLongAction = false
// the action will become available in 2sec
timeout = window.setTimeout(
() => {canDoLongAction = true},
2000
)
// you do your long action
alert("hey")
} else {
// if clicked while the timeout is going reset it
window.clearTimeout(timeout);
timeout = window.setTimeout(
() => {canDoLongAction = true},
2000
)
}
}
<button id="spamMe">spam me!!</button>
in the example, the button is blocked until you stop clicking for 2 seconds
I need to execute some function but if timeout expired I need to abort this function. I tried to use setTimeout and setImmediate. I wrote this example and used setInterval in callback for checking of working but it did't help me:
function waiter(timeout, fun) {
var functionHandler = setImmediate(fun);
var timeoutHandler = setTimeout(() => {
console.log('stoped');
clearImmediate(functionHandler);
clearTimeout(timeoutHandler);
}, timeout);
fun();
}
waiter(5000, () => {
setInterval(() => {
console.log('work');
}, 500);
});
After clearImmediate and clearTimeout my interval still working. How I understood that method doesn't guarantee that my function will be aborted.
Does anybody have an idea how to abort function execution?
UPDATE:
Yes, I know that I should call clearInterval but it's just an example for work checking. For example I should parse some big data and if it doesn't can do it by timeout I need to cancel this function execution and call something else.
The clearXXX functions don't abort functions that are currently running, they just remove functions from the async queue, so that they never start to run. JavaScript always executes code to its completion. You cannot interrupt code that's running in the main thread.
You need to name your interval
and clear it by its name. So your interval is no longer anonymous, but you've got a reference for it.
let counter = 10;
let newYearCountdown = setInterval( () => {
console.log(counter);
counter--
if (counter === 0) {
console.log("HAPPY NEW YEAR!!");
// here i clear interval by its name.
clearInterval(newYearCountdown);
}
}, 1000);