How setTimeout function is working in this case? [duplicate] - javascript

This question already has answers here:
Recursive setTimeout in javascript
(2 answers)
Closed 5 years ago.
<body>
<input type="text" value="10" id="txtBox" /><br/><br/>
<input type="button" value="Start Timer" onclick="startTimer('txtBox')" />
<input type="button" value="Stop Timer" onclick="stopTimer()" />
<script type="text/javascript">
var intervalId;
function startTimer(controlId)
{
var control = document.getElementById(controlId);
var seconds = control.value;
seconds = seconds - 1;
if (seconds == 0)
{
control.value = "Done";
return;
}
else
{
control.value = seconds;
}
intervalId = setTimeout(function () { startTimer('txtBox'); }, 1000);
}
function stopTimer()
{
clearTimeout(intervalId);
}
</script>
</body>
I am new to JavaScript. I was going through some tutorial, the above code snippet I came across, which works completely fine for starting a countdown timer from 10 to 0 in every 1000 millisecond interval. I am confused that how setTimeout() is calling the function repeatedly, when it is supposed to call the function only once after waiting 1000 millisecond.

function startTimer(){...} is a named function. One advantage of named function is that it call itself from inside its body. The code you shared is exploiting this concept & the code inside setTimeout is calling the same function startTimer
intervalId = setTimeout(function() {
startTimer('txtBox');
}, 1000);

The startTimer() function will be called by the setTimeout() function. Then when the startTimer() function is executing, it will call the setTimeout() function again. So it is a lot like a loop.
You can also use setInterval instead:
intervalId = setInterval(function(){
startTimer('txtbox');
}, 1000);
use it outside the startTimer function. It will call the startTimer function once every 1000 milliseconds repeatedly.

Related

way too keep function that called by event listener in execution

i try to make a button that get the time now ,put it in element and updated every one second using the event listener the problem that the time disappear immediately
var time
function updateTime(){
time = new Date().toLocaleTimeString();
document.getElementById('showtime').innerHTML=time
setInterval(updateTime, 1000);
}
document.getElementById("btnclock").addEventListener("click", updateTime);
html
<button id="btnclock"> Start Clock</button>
<p id='showtime'> </p>
Update can call setInterval(), but, as others have pointed out, we only want at most one interval timer running. This can be expressed tersely with a nullish coalescing assignment (not so tersely named).
Below, once the intervalID has been initialized, the setInterval() will no longer be evaluated. Keeping the interval id around is useful because it allows for a stop button, also demonstrated...
let intervalID;
function updateTime(run) {
document.getElementById('showtime').innerHTML = (new Date()).toString()
intervalID ??= setInterval(updateTime, 1000);
};
document
.getElementById("btnclock")
.addEventListener("click", updateTime);
document
.getElementById("btnclock-stop")
.addEventListener("click", () => {
clearInterval(intervalID)
intervalID = null; // so the setInterval assignment can run
});
<button id="btnclock"> Start</button>
<p id='showtime'>&nbsp</p>
<br/>
<button id="btnclock-stop"> Stop</button>
The issue is that when you click the button, updateTime function calls setInterval(updateTime, 1000) which creates a timer. The timer calls updateTime function every second. But updateTime creates another timer while the first one is still running. So in fact what is happening is that every second every running timer creates a new timer so after 10 seconds you will have 1024 timers running at the same time. This is obviously not what you want.
Try something like this:
var timer = 0;
function startTimer() {
if (!timer) {
timer = setInterval(updateTime, 1000);
}
}
function stopTimer() {
clearInterval(timer);
timer = 0;
}
function updateTime() {
var time = new Date().toLocaleTimeString();
document.getElementById("show-time").innerHTML = time;
}
document.getElementById("start-clock").addEventListener("click", startTimer);
document.getElementById("stop-clock").addEventListener("click", stopTimer);
<button id="start-clock">Start Clock</button>
<button id="stop-clock">Stop Clock</button>
<p id="show-time"></p>
It is important to destroy the timer when you no longer need it. Function clearInterval does it.

Javascript Behaviour [duplicate]

This question already has answers here:
Calling functions with setTimeout()
(6 answers)
Closed 2 years ago.
I am trying to make a seconds countdown with Javascript.
Here is my HTML
<div id="ban_container" class="error center">Please wait
<span id="ban_countdown" style="font-weight:bold">
45</span>
seconds before trying again
</div>
And my JS:
<script type="text/javascript">
var seconds = <?php echo $user->getBlockExpiryRemaining(); ?>;
function countdown(element) {
var el = document.getElementById(element);
if (seconds === 0) {
document.getElementById("ban_container").innerHTML = "done";
return;
}
else {
el.innerHTML = seconds;
seconds--;
setTimeout(countdown(element), 1000);
}
}
countdown('ban_countdown');
</script>
However for some reason, it is not waiting the timeout time, but instead executes countdown right away so that when I refresh the page it just displays "done" right away. I know it is actually being executed multiple times because if I do innerHTML += seconds + " "; it counts down from 45. Why is the timeout being bypassed?
setTimeout(countdown(element), 1000); executes your function with that argument and passes the result into setTimeout. You don't want that.
Instead, execute an anonymous function that calls your function:
setTimeout(function() {
countdown(el); // You used `el`, not `element`?
}, 1000);
If you'd like to pass an argument to a function by setTimeout, try this:
setTimeout(countdown, 1000, element);
The syntax of setTimeout is the following:
setTimeout(function,milliseconds,param1,param2,...)
It is because setTimeout is asynchroneous. Try this:
setTimeout(function(){
countdown('ban_countdown'); //or elemement
}, 1000);
This will make the function countdown execute after 1000 miliseconds.

Javascript or Jquery function with timer that resets each time it is called

I am looking for a way to call a function that should wait for 1000 miliseconds before executing. And when the function is called again before the 1000 miliseconds are reached, the timer should restart. So that the function runs 1000 miliseconds after the last time it was called.
So let's say I have a button:
<button type="button" id="btnclick">Click Me!</button>
And I want to display an alert after exactly 1000 miliseconds after the last time it was clicked. But when the button is clicked a second time, before the 1000 miliseconds have past, then the timer should restart.
If someone clicks the button 1 time, then the alert displays 1 second after the click.
If someone clicks the button, and then clicks again after 999 miliseconds, and then again after again 999 miliseconds, then I want to run the function 1 second after the last click (so 2,98 seconds after the first click).
Is this possible? And how?
My Best guess would be something like:
function delay(callback, ms) {
var timer = 0;
return function () {
var context = this, args = arguments;
clearTimeout(timer);
timer = setTimeout(function () {
callback.apply(context, args);
}, ms || 0);
};
}
$('#btnclick').click(function(e){
console.log('I want to see this everytime the button is clicked, without any delay');
delay(waitFunction(),1000);
});
function waitFunction(){
console.log('I want to see this 1 second after the LAST click');
}
(inspiration from: Wait for function till user stops typing )
Yes it is possible. you just have to check if an timeout is already counting down and, if it is, reset it. Here is a simple example.
// set timer-variable
var timer = null;
//on button-click
$('#btnclick').click (function (e) {
//clear timeout if already applied
if (timer) {
clearTimeout (timer);
timer = null;
}
//set new timeout
timer = setTimeout (function () {
//call wait-function and clear timeout
waitFunction ();
clearTimeout (timer);
timer = null;
}, 1000);
});
function waitFunction () {
console.log ('I want to see this 1 second after the LAST click');
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button type="button" id="btnclick">Click Me!</button>
I used lastclick variable to store date user clicked.
I defined lastclickworked variable to avoid double setTimeout calls. In settimeout function, i checked if 1 second passed, run the code. if 1 second doesn't passed then call settimeout again with 1 seconds- passed time
var lastclick=null;
var lastclickworked=true;
function clickMe(){
lastclick=new Date();
if(lastclickworked)
runcallback(1000);
}
function runcallback(milliseconds){
lastclickworked=false;
setTimeout(function(){
var current = new Date();
var milliseconds = (current.getTime() - lastclick.getTime());
if(milliseconds<1000){
runcallback(1000-milliseconds);
}else{
lastclickworked=true;
console.log('you clicked 1 second ago');
}
},milliseconds);
}
<button onclick="clickMe();">Click Me!</button>

Simple JavaScript counter function

I would like to make a counter function, and precise a variable for the starting time and the place to be displayed.
So if I would like to have many counter per page, I can easily manage it:
$(document).ready(function() {
// set time and place (where to display the counter)
function countDown(time, place){
if(time > 0){
time--;
setInterval(function(){countDown(time,place)}, 1000);
} // end if
if(time == 0)
{
window.clearInterval(time);
}
} // end function
$('.click').click(function(){
countDown(30, '#counter');
});
}); // end DOM
</script>
</head>
<body>
<div class="click">clickme</div>
<br />
<div id="counter">30</div>
</body>
Try this:
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js">
</script>
<script>
var myVar;
var clickcount=0;
function countDown (time, place) {
if (time > 0) {
$(place).html(time);
time--;
myVar=setTimeout(function () { countDown(time, place); }, 1000);
}
}
function startreset(time,place){
clickcount++;
if(clickcount % 2 === 0){
clearTimeout(myVar);
} else {
countDown(time,place);
}
}
$('.click').click(function(){
startreset(30, '#counter');
});
</script>
</head>
<body>
<div class="click" onClick="javascript:countDown(30,'#counter');">clickme</div>
<br />
<div id="counter">30</div>
</body>
The problem you are likely having is that you are calling setInterval multiple times. setInterval does more than just wait the x milliseconds you tell it to and then call your method, it continues to call your method every subsequent x milliseconds. So, when you call countDown the first time, an interval is set for your function. That interval expires and countDown is called again. All fine so far, but now the second call to countDown establishes ANOTHER setInterval. The program will wait your x milliseconds to call countDown from the second setInterval, but it will call it from the first setInterval sooner.
...In other words, you shouldn't be repeatedly calling setInterval. What you want is setTimeout, which waits the specified amount of time and then calls the specified method once.
function countDown (time, place) {
if (time > 0) {
time--;
$(place).html(time);
setTimeout(function () { countDown(time, place); }, 1000);
}
}
Alternatively, if you're not feeling recursive today:
function countDown (time, place) {
var interval = setInterval(function () {
if (time > 0) {
time--;
$(place).html(time);
} else {
window.clearInterval(interval);
}
}, 1000);
}
which leverages setInterval, BUT ONLY ONCE.
JSFiddle provided: http://jsfiddle.net/LKvBR/

setTimeout() is not waiting [duplicate]

This question already has answers here:
Calling functions with setTimeout()
(6 answers)
Closed 2 years ago.
I am trying to make a seconds countdown with Javascript.
Here is my HTML
<div id="ban_container" class="error center">Please wait
<span id="ban_countdown" style="font-weight:bold">
45</span>
seconds before trying again
</div>
And my JS:
<script type="text/javascript">
var seconds = <?php echo $user->getBlockExpiryRemaining(); ?>;
function countdown(element) {
var el = document.getElementById(element);
if (seconds === 0) {
document.getElementById("ban_container").innerHTML = "done";
return;
}
else {
el.innerHTML = seconds;
seconds--;
setTimeout(countdown(element), 1000);
}
}
countdown('ban_countdown');
</script>
However for some reason, it is not waiting the timeout time, but instead executes countdown right away so that when I refresh the page it just displays "done" right away. I know it is actually being executed multiple times because if I do innerHTML += seconds + " "; it counts down from 45. Why is the timeout being bypassed?
setTimeout(countdown(element), 1000); executes your function with that argument and passes the result into setTimeout. You don't want that.
Instead, execute an anonymous function that calls your function:
setTimeout(function() {
countdown(el); // You used `el`, not `element`?
}, 1000);
If you'd like to pass an argument to a function by setTimeout, try this:
setTimeout(countdown, 1000, element);
The syntax of setTimeout is the following:
setTimeout(function,milliseconds,param1,param2,...)
It is because setTimeout is asynchroneous. Try this:
setTimeout(function(){
countdown('ban_countdown'); //or elemement
}, 1000);
This will make the function countdown execute after 1000 miliseconds.

Categories

Resources