I am trying to display several count down timers on same page. now as far as i know there are 2 ways of doing it without using jquery plugins or some other scripts (if you know of a good one please let me know)
starting 1 sec setInterval and a global variable that will contain milliseconds and then just reduce -1000 every interval.
creating a function that reduce 1 sec from a global variable and then at the bottom of that function setting a setTimeout of 1 sec that will run that functions so basically recursion every 1 sec.
My question is which of the 2 options will work better and/or faster?
here is demonstrative code for both:
setInterval:
var amount_of_seconds_left = 46800000;
setInterval(function(){
if(amount_of_seconds_left > 1000){
amount_of_seconds_left -= 1000;
}
},1000);
setTimeout:
var amount_of_seconds_left = 46800000;
function startTime(){
if(amount_of_seconds_left > 1000){
amount_of_seconds_left -= 1000;
t=setTimeout(function(){startTime()},1000);
}
}
Both ways could work but i was wondering performance wise which is better and is performance is even an issue with this ?
setInterval and setTimeout don't start after 1000ms e.g. if another script is running, so both can cause delays. It would be better to use the setIntervall to call the display update only and use the the Date object to calculate the exactly remaining time. E.g. after the browser was busy the timer shows the correct time after the next update.
Here an example:
HTML:
<div id="timer1"></div>
<div id="timer2"></div>
javascript:
// update all timer
function updateTimer() {
for (var i in aTimer) {
var oTimer = document.getElementById(aTimer[i].sId);
var iSeconds = parseInt((aTimer[i].iFinished - Date.now()) / 1000);
oTimer.innerHTML = iSeconds;
}
}
// Init all timers with DOM-id and finish time
var aTimer = [
{ sId: 'timer1', iFinished: Date.now() + 46800000 },
{ sId: 'timer2', iFinished: Date.now() + 780000}
];
// call display update
setInterval(function() {
updateTimer();
}, 333);
I belive that the setInterval code executes every 1000ms exactly, while the setTimeout waits 1000ms, runs the function, which takes some ms, then sets another timeout. So the wait period is actually greater than 1000ms.
From this post:
setTimeout or setInterval?
Related
I cant understand how and why cant i use a specific set time like 2000 to iterate over some numbers with a delay of 2 seconds instead of i*2000 in setTimeout()
function timer() {
for (let i = 0; i < 10; i++) {
setTimeout(function () {
console.log(i);
}, i * 2000);
}
}
timer();
Because if you use the static value 2000 then all 10 values will be logged to the console simultaneously after 2 seconds. The intent instead is to log a value every two seconds. So the first log is at 2000, then 4000, then 6000, etc.
why cant i use a specific set time like 2000 to iterate over some numbers
You may be looking for setInterval instead of setTimeout. Something like this:
let x = 1;
let i = setInterval(function () {
console.log(x++);
if (x > 10) {
clearInterval(i);
}
}, 2000);
Conceptually the two approaches are meant to accomplish the same thing. The version in the question does so with a kind of artificial interval by creating a finite set of multiple staggered timeouts, whereas this version creates and clears an interval.
This is in a loop so it progressively adds longer delays before running the callback hence the scale value i. Of course this could be solved with a setInterval and a clearInterval.
I work on CodeHS and need to make a countdown timer for my powerups in the game I'm making, Breakout. I need the timer to be reusable so no for loops, it needs to go down in seconds/milliseconds (it doesn't matter which) and preferably last 30 seconds or 30,000 milliseconds. Remember this is CodeHS I'm working on.
If you want something to happen 30 seconds after you start your timer you could do something like this:
//set the time remaining to 30 outside of a function so it is global
var timeRemaining = 30;
function start(){
//set the timer to run the function countdown once every second(1000 milliseconds)
setTimer(countdown, 1000)
}
function countdown(){
/*every time it is called this function subtracts one from the time if it is
more than 30, when it reaches 0 stops the timer and resets the time*/
if(timeRemaining<=0){
stopTimer(countdown);
timeRemaining = 30;
println("Done");
//30 seconds has passed, do what you need here(call your function)
}else{
timeRemaining--;
println(timeRemaining+" seconds left")
}
}
Add your function or whatever you want to happen after the time is up whereprintln("Done") is.
Because timeRemaining is set back to 30 at the end, you can reuse the timer by calling setTimer(countdown, 1000) again.
You can remove the println statments, they are just to see what is happening.
If CodeHS doesn't want hardcoded numbers (I think they call them "magic numbers"), replace the 30s with a constant set to 30.
Let me know if you need a better explanation.
Tell me if I'm wrong because I have no idea what CodeHS is, but I am quite sure that this can be achieved with a simple setInterval function.
To go by full seconds:
var timer=30;
setInterval(function(){
timer-=1;
document.getElementById(timerId). innerHTML=timer;//shows the remaining time
}, 1000);//subtracts 1 second from timer each second
To go by tenths of a second
var timer=30.0;
setInterval(function(){
timer-=0.1;
document.getElementById(timerId). innerHTML=timer;//shows the remaining time
}, 1000);//subtracts a tenth second from timer every 0.1 seconds
var timeLeft = 60;
var txt = new Text(" ","30pt Arial");
function start(){txt.setPosition(200,200); txt.setColor(Color.black); add(txt); setTimer(countdown,1000);}
function countdown(){drawTimer(); timeLeft--;}
function drawTimer(){txt.setText(timeLeft);}
I am interested in designing a timed quiz questions which submit themselves after 30 seconds or so. Following this other SO request I have coded the following:
<script>
var counter = 30;
var interval = setInterval(function() {
counter--;
// Display 'counter' wherever you want to display it.
document.getElementById("counter").innerHTML = "Timer:"+counter
if (counter == 0) {
// Submit form
test.submit('timeout');
}
}, 1000);
</script>
<p id="counter"></p>
This seems to work on most modern browsers. There is a problem however that this seems to work fine for the first question or form. I think the second form defines an additional function which causes the countdown to go twice as fast. Then the third, three times as fast, etc. Is there a way to ensure that this function is only defined once?
Thanks for any help you can provide. I am new to javascript so I apologize in advance if I have used the wrong terminology.
The first time you call setInterval(), it defines an interval that will decrement the counter by 1 every second. It doesn't stop once the counter reaches 0; it just keeps decreasing it every second. Then you call setInterval() again, which sets up another decrement of the same counter every second. So now the counter gets decremented twice per second: once because of the first interval you set up and another time because of the second interval. The effect just builds up as you add more intervals.
You can see the effect in this fiddle.
The solution is just to stop the interval once the counter reaches 0, before you set up another interval. Besides, there's no need to use the same counter variable for all the different intervals, so you can just declare a new variable each time in a narrower scope. Narrowing the scope of variables will minimize the risk of different pieces of code interfering with each other.
function startCountDown(){
// This counter is local to this invocation of the "startCountDown"
// function.
var counter = 10;
var interval = setInterval(function() {
counter--;
// Display 'counter' wherever you want to display it.
document.getElementById("counter").innerHTML = "Timer:"+counter
if (counter == 0) {
// Submit form
console.log("Form submitted!");
// Stop this interval so that it doesn't update the
// interface anymore (next interval will take care of that).
clearInterval(interval);
startCountDown();
}
}, 1000);
}
startCountDown();
This other fiddle shows the solution.
I want to create a timer that once it reaches a certain point, the timer resets, and then starts over.
Right now, I've got the loop set up, and as a test I want it to reset after 5000 ms (5 seconds). But the counter goes all haywire.
WIP Demo here: http://jsfiddle.net/stursby/wUHA3/
Instead of setTimeout, consider using setInterval. It will repeat automatically until you clear the interval.
setInterval(myMethod, 5000);
function myMethod( )
{
//this will repeat every 5 seconds
//you can reset counter here
}
I agree with keyboardP that you should probably be using setInterval instead of setTimeout. However, to answer your original question the reason you are having issues with the timer is because of your repetition logic. Don't use:
var diff = (new Date().getTime() - start) - time;
window.setTimeout(instance, (100 - diff));
You don't need to try and account for execution time (which I assume is what you were trying to do with diff). Just assume it is negligible and use:
setTimeout(instance, 100);
And your issue is resolved, as you can see in this jsFiddle.
I have the following script in a js file:
// Ad score
var score = 0;
//$('#score').text(score);
function foundMatchingBlocks(event, params) {
params.elements.remove();
score += 100;
$('#score').text(score);
};
Now on each matching, 100 points are added to var score. This all works. Now I want to extend this a bit. As soon as the page loads I want to start a countdown to reduce the number of points (starting with 100) with 1 point a second for 60 seconds. So the minimum number of points a user can get is 40. When someone gets the points, the counter should reset and countdown again.
Example:
Page loads (timer starts from 100)
User has a match after 10 seconds (+90 points are added)
Counter resets and countdown from 100 again
User found a match after 35 sec (+65 points are added)
etc etc
Problem is, I have no idea how to do this :( Hope someone can help me with this.
The above is fixed, thanks all for helping!!!
The big picture is, you'll need to become pretty familiar with timeouts and intervals in javascript. This is the reference page I keep going back to when I need to refresh my memory: http://www.elated.com/articles/javascript-timers-with-settimeout-and-setinterval/
For your specific task, you'll probably want to use an Interval that triggers every 1000 milliseconds to calculate the second-by-second point reduction, and a separate Timeout for failure that resets every time the user completes their challenge.
Here are a few tips for working with timeouts and intervals that usually lead to followup questions:
When you set a timeout, always capture the return value (I think it's basically a random integer). Save it to some global var for convenience.
var failureTimer; // global var high up in your scope
failureTimer = setTimeout ( "gameOver()", 100000 ); // 100 seconds * 1000ms
Then in whichever method gets called when the player completes their challenge, you call this:
clearTimeout (failureTimer); // resets the timer and gives them another 100 seconds
failureTimer = setTimeout ( "gameOver()", 100000 ); // yes call this again, to start the 100 sec countdown all over again.
The second pain point you're likely to encounter when working with Timeouts and Intervals is how to pass parameters to the functions like gameOver() in my example above. You have to use anonymous functions, as described here:
Pass parameters in setInterval function
For more on anonymous functions, this is a good overview:
http://helephant.com/2008/08/23/javascript-anonymous-functions/
Good luck with your project! Let me know if you have any questions.
Here's some code without the use of timers. Call startCountdown() every time you want to re-initialize the count-down. Call getAvailableScore() when you want to fetch the current available score. You will have to decide what to do when the available score goes to zero.
var beginCountDownTime;
function startCountdown() {
beginCountDownTime = new Date();
}
function getAvailableScore {
var now = new Date();
var delta = (now.getTime() - beginCountDownTime.getTime()) * 1000; // time elapsed in seconds
var points = 100 - (delta / 60);
return(Math.round(Math.max(points, 0))); // return integer result >= 0
}
Maybe something like:
// Ad score
var score = 0;
var pointsAvailable = 100;
//$('#score').text(score);
function foundMatchingBlocks(event, params) {
params.elements.remove();
score += pointsAvailable;
$('#score').text(score);
pointsAvailable = 100;
};
$(document).ready(function() {doTimer();});
function doTimer() {
setTimeout('reducePoints()',1000);
}
function reducePoints() {
if(pointsAvailable>40) {
pointsAvailable--;
}
doTimer();
}