I have similar code to what is below and the setInterval is running a lot faster than 1000ms and it crashes/ slows down the page.
var checkDiffTest = function(){
console.log('test checkDiff init');
var interval = setInterval(countdownTest(), 1000);
}
var countdownTest = function(){
console.log('test countdown init');
checkDiffTest();
}
countdownTest();
You are setting a new interval each time the interval runs:
Your interval calls countdownTest()
Which called checkDiffTest()
Which creates a new interval (while the last one is still running)
A new 1000ms interval is started every 1000ms.
It looks as though you want setTimeout() instead.
Also countdownTest() as setInterval's first parameter invokes that function straight away. You want to pass the function as reference:
var checkDiffTest = function(){
console.log('test checkDiff init')
var interval = setTimeout(countdownTest, 1000);
}
var countdownTest = function(){
console.log('test countdown init');
checkDiffTest();
}
countdownTest();
Related
My setTimeout() function works, but my clearTimeout() is not working. Even though I have an 'if' statement that's supposed to run the clearTimeout function once my variable 'secs' is less than 0, the timer keeps counting down into negative numbers. When I type my variable name, 'secs' into the console, I get undefined, even though it's defined as a parameter in the function called by my setTimeout. I don't know what I'm doing wrong. Can anyone help, please?
My full code is at https://codepen.io/Rburrage/pen/qBEjXmx;
Here's the JavaScript snippet:
function startTimer(secs, elem) {
t = $(elem);
t.innerHTML = "00:" + secs;
if(secs<0) {
clearTimeout(countDown);
}
secs--;
//recurring function
countDown = setTimeout('startTimer('+secs+',"'+elem+'")', 1000);
}
Add a condition to call recursive function like below.
if (secs < 0) {
secs = secsInput;
}
//recurring function
countDown = setTimeout('startTimer('+secs+',"'+elem+'")', 1000);
For a countdown timer, I would recommend using setInterval and clearInterval instead. setInterval will repeatedly run the callback function for you. It might look like this:
let countdown;
function startTimer(secs, elem) {
countdown = setInterval(function(){
t = $(elem);
t.innerHTML = "00:" + secs;
secs--
if (secs < 0) {
clearInterval(countdown);
}
}, 1000);
}
By the time you call clearTimeout(countDown), countDown refers to the previous timeout, that already timed out. It will not stop the one yet to start. You could just not re set the timeout, like
if(!/*finished*/) setTimeout(startTimer, 1000, secs, elem);
In your case, it's more convenient to use setInterval and clearInterval.
To keep the setTimeout and clearTimeout functions, you should add return in the if statement.
function startTimer(secs, elem) {
t = $(elem);
t.innerHTML = "00:" + secs;
if(secs<0) {
clearTimeout(countDown);
return;
}
secs--;
//recurring function
countDown = setTimeout('startTimer('+secs+',"'+elem+'")', 1000);
}
So there are 4 events in my opinion that will have to be addressed by the timer:
The quiz starts
The quiz ends
The timer runs out
The player answers a question
This can be solved by a function returning an object with some options.
The createTimer can be used to set the parameters for the timer.
Point 1. would be timer.start() --> will start a timer with the parameters
Point 3. can be addressed with the callback that will be called if the timer runs out --> createTimer(5,'display', ()=>{ // your code goes here })
Point 2. can be achieved with --> timer.stop()
Point 4. is needed when the timer needs to be reset without running out timer.reset()
Further on the interval is not in the global scope so you could have multiple timers with different settings and they wouldn't interfere with each other
// function for creating the timer
function createTimer(seconds, cssSelector, callbackOnTimeout) {
// interval the timer is running
let interval;
// the html node where innerText will be set
const display = document.getElementById(cssSelector)
// original seconds passt to createTimer needed for restart
const initSec = seconds
// starting or continuing the interval
function start() {
// setting interval to the active interval
interval = setInterval(() => {
display.innerText = `00:${seconds}`;
--seconds;
if (seconds < 0) {
// calling restart and callback to restart
callbackOnTimeout()
restart()
}
}, 1000);
}
// just stopping but not resetting so calling start will continue the timer
// player takes a break
function stop(){
clearInterval(interval)
}
// opted for a restart and not only a reset since it seemed more appropriate for your problem
function restart(){
clearInterval(interval)
seconds = initSec
start()
}
// returning the object with the functions
return {
start: start,
stop: stop,
restart: restart
}
}
// example for creating a timer
const timer1 = createTimer(5,'display',()=>{
console.log(`you where to slow ohhh...`)
})
// calling the timer
timer1.start()
I am trying to change the speed of the interval for calling a function.
The first time it should take a second, and the rest should take nine seconds to call.
var tiempoCaratula=1000;
var refreshCaratula = setInterval(function() {
$('.col-2').load('caratula.php');
}, tiempoCaratula);
Run the first one using setTimeout and then schedule it for future runs in whatever interval you need to.
var myFunction = function() {
$('.col-2').load('caratula.php');
}
var refreshCaratula;
// call the function after 1000ms
setTimeout(function () {
myFunction();
// then schedule it to run every 9000ms
refreshCaratula = setInterval(myFunction, 9000);
}, 1000);
You could make a timeout that runs once at one second and a sub interval that runs every nine seconds after the timeout.
var tiempoCaratula = 1000;
var tiempoCaratula2 = 9000;
var refreshCaratula = setTimeout(function() {
$('.col-2').load('caratula.php');
var refreshCaratula2 = setInterval(function() {
$('.col-2').load('caratula.php');
}, tiempoCaratula2);
}, tiempoCaratula);
I want a counter which reset in specific interval of time. I wrote this code. When I refresh the page it is executing perfectly. But as time passes the timer goes really fast, skipping seconds. Any idea why this is happening.
function countdown_new() {
window.setInterval(function () {
var timeCounter = $("b[id=show-time]").html();
var updateTime = eval(timeCounter) - eval(1);
$("b[id=show-time]").html(updateTime);
if (updateTime == 0) {
//window.location = ("ajax_chart.php");
$("b[id=show-time]").html(5);
clearInterval(countdown_new());
// countdown_new();
//my_ajax();
}
}, 1000);
}
window.setInterval(function () {
countdown_new();
}, 5000)
HTML
Coundown in 5 seconds
The issue is because you are not clearing the previous timer before starting a new one, so you start a new one for each iteration. To clear the timer you should save a reference to it, and pass that to clearInterval, not a function reference.
Also, note that your pattern of using multiple intervals for different operations can lead to overlap (where two intervals are acting at the same time and cause odd behaviour). Instead, use setTimeout for the initial 5 second delay and then chain further calls to stop this overlap.
Try this:
var timer;
function countdown_new() {
timer = setInterval(function () {
var $showTime = $("#show-time")
var updateTime = parseInt($showTime.text(), 10) - 1;
$showTime.html(updateTime);
if (updateTime == 0) {
$showTime.html('5');
clearInterval(timer);
setTimeout(countdown_new, 5000);
}
}, 1000);
}
setTimeout(countdown_new, 5000);
Example fiddle
Note that you should use the # selector to select an element by its id attribute, and you should never use eval - especially not for type coercion. To convert a value to an integer use parseInt().
You are calling window.setInterval(), which schedules a function call to countdown_new() ever 5 seconds without stop.
Compounding the problem, you are calling countdown_new() again inside your clear interval.
You need to call setInterval just once to continuously execute a function every 5 seconds.
If you want to cancel an interval timer, you need do to this:
var intervalObj = setInterval(function() { ... }, 5000);
clearInterval(intervalObj);
Yes clearinterval does the trick.
function countdown_new(){
t = window.setInterval(function() {
var timeCounter = $("b[id=show-time]").html();
var updateTime = eval(timeCounter)- eval(1);
$("b[id=show-time]").html(updateTime);
if(updateTime == 0){
//window.location = ("ajax_chart.php");
$("b[id=show-time]").html(5);
clearInterval(t);
// countdown_new();
my_ajax();
}
}, 1000);
}
The timing value in setInterval determines the next time at which the function is going to be invoked again. For example:
t = 8000;
myFunction(){
if (someCondition){
//halt setInterval
//t = 5000;
// setInterval(myFunction,t);
}
// do some logic
}
setInterval(myFunction, t);
The problem is changing of t will not affect the time that I want the current call to be remained before the next call. In other words, is there any way to halt setInterval and then I can reset it again with new time?
If you want to do something like that, you're better off doing your own interval control with setTimeout.
var shortInterval = 2000, longInterval = 4000;
function timerCode() {
// do something
if (whatever) {
setTimeout(timerCode, shortInterval);
}
else {
setTimeout(timerCode, longInterval);
}
}
setTimeout(timerCode, longInterval);
That way, on each iteration of the timer you can decide how long it should be until the next iteration. If you want to stop, just don't reset the timer at all.
You have to use clearInterval().
var myInterval = setInterval(myFunction, t);
...
clearInterval(myInterval);
...
myInterval = setInterval(myFunction, 1000);
I want to execute a piece of arbitrary code and be able to stop it whenever I want. I figured I could do this with setTimeout and then use clearTimeout to stop it. However if the code in the timeout creates it's own timeouts, then those keep executing even after I clear the original.
Example:
var timeoutID = setTimeout(
function(){
console.log("first event can be stopped with clearTimout(timeoutID)");
setTimeout(function(){console.log("but not this one")}, 5000)
}, 5000)
Now one way would be to control the code being executed and make it store the value of any additional timeouts into a global variable and clear them all at once. But is there a better way to do this? And is there a way to do this on arbitrary code?
To clarify, I'm trying to be able to execute any function I want, then stop it whenever I want, even if the function contains timeouts
You can put the inner timeout into a variable too:
var innerTimeout,
timeoutID = setTimeout(
function(){
console.log("first event can be stopped with clearTimout(timeoutID)");
innerTimeout = setTimeout(function(){console.log("but not this one")}, 5000);
}, 5000);
You would have to create an array of timeout IDs such as this:
var timeoutIds = [];
timeoutIds.push(setTimeout(
function(){
console.log("first event can be stopped with clearTimout(timeoutID)");
timeoutIds.push(setTimeout(function(){console.log("but not this one")}, 5000));
}, 5000))
And then to clear:
for (int i = 0; i < timeoutIds.length; i++)
{
clearTimeout(timeoutIds[i]);
}
timeoutIds = [];
You could wrap your timeouts in an object or re use timeoutID for the second timeout.
Wrap in an object:
function Timer(){
var me=this;
this.currentTimerID=setTimeout(function(){
console.log("First timeout");
me.currentTimerID=setTimeout(function(){
console.log("Second timeout");
},100);
},100);
};
Timer.prototype.cancel=function(){
clearTimeout(this.currentTimerID);
};
var t = new Timer();//let this run it's course
setTimeout(function(){t = new Timer()},250);//start timer again
setTimeout(function(){t.cancel();},400);// cancel it after the first timeout
Re use timeoutID:
var timeoutID = setTimeout(
function(){
console.log("first event can be stopped with clearTimout(timeoutID)");
timeoutID=setTimeout(function(){console.log("but not this one")}, 100)
}, 100)
setTimeout(function(){
clearTimeout(timeoutID);
},150);// will not execute the second timeout
One tip: If you're testing code with timeout then don't use such high values as it'll take 10 seconds for your original code to run.