I'm working on some code that'd I'd like to have each loop run every 60 seconds, but currently each loop runs immediately. The purpose of the code it to see if a form has changed, and if it has save the form. Do I have setInterval setup incorrectly?
function saveHelper(formId) {
for(var i = 0; i < 4; i++) {
save(formId);
}
}
function save(formId) {
console.log('might save');
var changed = formChanges(formId);
var intId = setInterval(stall, 60000);
if(changed.length > 0) {
console.log('would save');
//document.getElementById(formId).submit();
}
clearInterval(intId);
}
function stall() {
return true;
}
You are treating interval as some sort of synchronous sleep method, which is not the case. The change code should be inside of the setInterval, it should not live after the interval.
var intId = setInterval(function () {
if(changed.length > 0) {
console.log('would save');
//document.getElementById(formId).submit();
}
}, 60000);
setInterval doesn't pause your code, it just schedules some code to be run some time in the future. For example, when you do this:
var intId = setInterval(stall, 60000);
That says "every 60000 milliseconds, run the function stall". As soon as this line of code completes, it will immediately run your next line of code, do the saving, then clear the interval. Clearing the interval cancels it, so now nothing will happen in 60000 milliseconds.
Instead, you'll want to do something like this:
function saveHelper(formId) {
let count = 0;
const intId = setInterval(function () {
if(changed.length > 0) {
console.log('would save');
//document.getElementById(formId).submit();
}
count++;
if (count === 4) {
clearInterval(intId);
}
}, 60000);
}
Every 60000 milliseconds, the inner function will run, and do the saving. After saving, it checks how many times we've done this, and once it reaches 4, it clears the interval to stop it from happening any more.
Related
function tick() {
seconds_lapsed++; // Break point.
}
function countdown() {
while(!stopped || !is_paused()){
setTimeout(tick, 1000); // 1 second.
show_counter();
}
}
Could you tell me why the interpreter doesn't stop at the breakpoint? The while loop works, hava a look at the screenshot.
The while loop is a "busy" loop, i.e. it keeps the JavaScript engine busy, so it will not process anything that is waiting in one of its event/job queues. This means that the user interface does not get updated, no input can be processed, and events produced by setTimeout are not consumed. In this example, tick can only get executed if the currently running code finishes. So the while loop must end first.
You should let tick execute, and only then check the condition:
var stopped = true;
var seconds_lapsed = 0;
document.querySelector("button").addEventListener("click", function() {
stopped = !stopped;
seconds_lapsed = 0;
this.textContent = stopped ? "Start" : "Stop";
if (!stopped) countdown();
});
function show_counter() {
document.querySelector("span").textContent = seconds_lapsed;
}
function is_paused() {
return document.querySelector("input").checked;
}
function tick() {
seconds_lapsed++;
}
function countdown() {
show_counter();
setTimeout(function () {
if (stopped) return; // stop the loop
if (!is_paused()) tick();
countdown(); // <--- this is the "loop"
}, 1000);
}
Seconds elapsed: <span>0</span><br>
<input type="checkbox">Paused<br>
<button>Start</button>
the following example might help you accomplish what you are after. Distinguish between setInterval() and setTimeout()
Basically the docs say:
setTimeout executes a function or specified piece of code once the timer expires.
setInterval repeatedly calls a function or executes a code snippet, with a fixed time delay between each call.
So if you use setInterval you don't need a while loop inside because it is already called "repeatedly"
var counter = $('#counter');
var stopped = false;
var seconds_lapsed=0;
var myInterval;
function tick() {
if(stopped) {
clearInterval(myInterval);
show_counter('FINISHED');
return;
}
show_counter(seconds_lapsed++);
}
function show_counter(message){
counter.html(message);
}
function countdown() {
myInterval = setInterval(tick, 1000);
}
function endCountdown(timeout) {
let timeoutId = setTimeout(function(){
stopped = true;
clearTimeout(timeoutId)
}, timeout);
}
countdown(); // start the countdown
endCountdown(5000); // ends the countdown after 5000 ms => 5sec
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="counter">counter</div>
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 want to execute a block of code every two seconds—to accomplish this, I thought the easiest way would be to retrieve the current system time as so:
if ((Date().getSeconds()) % 2 == 0) {
alert("hello"); //I want to add code here!
}
However, my alert is not printing to the screen every two seconds. How can this be properly implemented?
In order to run a block of code every x seconds, you can use setInterval.
Here's an example:
setInterval(function(){
alert("Hello");
}, x000); // x * 1000 (in milliseconds)
Here's a working snippet:
setInterval(function() {
console.log("Hello");
}, 2000);
You can use setInterval(). This will loop every 2 seconds.
setInterval(function() {
//something juicy
}, 2000);
Try using the setInterval() method
setInterval(function () {console.log('hello'); }, 2000)
This should work for you.
setInterval(function() {
//do your stuff
}, 2000)
However, to answer why your code is not working, because it is not in a loop.
runInterval(runYourCodeHere, 2);
function runInterval(callback, interval) {
var cached = new Array(60);
while (true) {
var sec = new Date().getSeconds();
if (sec === 0 && cached[0]) {
cached = new Array(60);
}
if (!cached[sec] && sec % interval === 0) {
cached[sec] = true;
callback();
}
}
}
function runYourCodeHere() {
console.log('test');
}
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);
}
There is a function which sets an interval using setInterval(), but even after calling clearInterval(), I can see in the console that the else condition is still running. How can I clear that interval properly?
function increase(old, step, neu) {
var i = 0;
var delay2;
function countUp() {
if (i < 5) {
old += step;
// console.log("increase")
$("#total-price-value").text(old + " dollors");
$("#total-price-value").digits();
i++;
delay2 = setInterval(countUp, 80);
} else {
clearInterval(delay2);
console.log(delay2);
}
}
countUp();
}
It looks like you're a little confused about the difference between timeouts and intervals. Timeouts fire only once; intervals fire many times. If you're using an interval, you probably only want to set it once (you're setting it every time). If you're using a timeout, you probably want to set it every time (like you're doing).
In order to fix the problem, you'll either want to switch to timeouts (probably the easiest; just a search/replace) or only set the interval once.
For example, here is how one might use setTimeout to count up to five:
var count = 0;
function timeoutFired() {
count++;
if(count < 5) {
setTimeout(timeoutFired, 1000);
}
}
setTimeout(timeoutFired, 1000);
Using timeouts, we don't need to clear to stop it from counting; simply not setting a timeout will prevent it from running again.
Here is how one might use setInterval:
var count = 0;
function intervalFired() {
count++;
if(count >= 5) {
clearInterval(interval);
}
}
var interval = setInterval(intervalFired, 1000);
If you want some code running periodically using intervals to stop, you must call clearInterval. Note that we only call setInterval once, versus setTimeout every time we didn't want it to continue.
Apparently, you have mistaken setInterval for setTimeout. setInterval runs the enclosed function every n milliseconds while setTimeout executes only once after n milliseconds.
I suppose you wanted to "tick until 5" so here's a sample:
function increase(old, step, neu) {
var i = 0;
interval = setInterval(function() {
if (i < 5) {
//do something at this "tick"
console.log(i);
i++;
} else {
//else, stop
clearInterval(interval);
}
},80);
}
increase();