Executing code inside setInterval function only once per few seconds - javascript

I'm working on a simple project that is HTML and Javascript; and I have a problem with my timer.
I'm calculating the seconds between two Date() objects; and every 2 seconds, I want to get a new random number. I have a setInterval that runs every 100 ms and when I get past the 2 second mark, the code inside the if statement should run.
So my question is:
How can I make sure the code execute only once per 2 seconds in an if statement that is inside a setInterval() that runs every 100 ms?
Here is the code:
var startTime = new Date();
var endTime = new Date();
var randomNumber = 0;
var gameTimer = setInterval(function(){
//calculate seconds;
var secondsPassed = Math.round( (endTime - startTime) / 1000 );
if(modulo(secondsPassed,2) == 0){
//when the "gate" is open this keep executing every 100 mili seconds.
//but i want it to execute only once every 2 seconds.
randomNumber = Math.floor(Math.random()*lanes.length);
$(lanes[randomNumber]).append(box);
}
endTime = new Date();
}, 100);
var modulo = function (n, m) {
var remain = n % m;
return Math.floor(remain >= 0 ? remain : remain + m);
};

I think you are asking for a double-interval timer.
var interval = 100, beat = 2000, ticks = 0;
var timer = setInterval(function(){
runsEvery100ms(); // ««« Code here runs every 100 ms.
if (ticks > 0 && ticks % beat === 0) {
runsEvery2000ms(); // ««« Code here runs every 2000 ms.
ticks = 0;
}
ticks += interval;
}, interval);
Demo Fiddle here.

Related

Error with count up when use setInterval and clearInterval

I use countTime function for incrementing timer, I have 1 function gameStart to initialize game structures and assign variable totalSecond = 0 and variable timeStart = setInterval(countTime, 1000). I have a button that when clicked it will run the function gameStart. When I run the code for the first time, everything is fine, but when I press the button many times with the newGame event, it increases the time very quickly. I have to clearInteval when I lose the game so time can stop. Thank for help me
function countTimer() {
totalSeconds++;
var hour = Math.floor(totalSeconds /3600);
var minute = Math.floor((totalSeconds - hour*3600)/60);
var seconds = totalSeconds - (hour*3600 + minute*60);
if(hour < 10)
hour = "0"+hour;
if(minute < 10)
minute = "0"+minute;
if(seconds < 10)
seconds = "0"+seconds;
document.getElementById("countUp").innerHTML = hour + ":" + minute + ":" + seconds;
}
function gameStart() {
timerVar = setInterval(countTimer, 1000);
totalSeconds = 0;
rows = parseInt(document.getElementById("rows").value);
cols = parseInt(document.getElementById("cols").value);
mineCount = parseInt(document.getElementById("mines").value);
rows = rows > 10 ? rows : 10;
cols = cols > 10 ? cols : 10;
mCount = mCount > 10 ? mCount : 10;
openedCells=0;
initBoard();
initHTML();
}
setInterval functions never expire until you call clearInterval. In your case, every time you run gameStart, a new interval is created that counts up.
You are left with multiple intervals, making the timer go up quicker and quicker.
A quick fix would be to declare timerVar outside the Function, then clear and re-make it every time gameStart is called.
timerVar = setInterval(()=>{},1000) // Empty interval
function gameStart() {
clearInterval(timerVar)
timerVar = setInterval(countTimer, 1000);
totalSeconds = 0;
I'm unable to test this at the moment, but it should work.

setinterval vs settimeout

How can run a countdown timer at 7:50 AM for 10 minutes until 8:00AM everyday. After that the shift will close. the timer will be a warning for finishing the work.
I used different flavours of setinterval and settimeout code snippets for some hours now. but i don't know how to proceed.My main question is to use setinterval or setimeout.
1) setinterval: is checking the that the time is 7:50 after every few minutes is ok?
2) settimeout: is it ok to count the seconds of the day. and then proceed with calling the function after those seconds?
This works for me
window.setInterval(function() {
var date = new Date();
if (date.getHours() === 8 && date.getMinutes() === 0) {}
}, 60000);
var now = new Date();
var millisTill10 = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 10, 0, 0, 0) - now;
if (millisTill10 < 0) {
millisTill10 += 86400000;
}
setTimeout(function() {
alert("It's 10am!")
}, millisTill10);
Run a timer for every minute. Show your warning if the current time falls within your allocation. The problem with this code is that it is only accurate up to a minute - not up to the second.
And running this every second is not a good practice.
setInterval(function(){
var d = new Date();
var h = d.getHours();
var m = d.getMinutes();
//Rough estimation for the time between 7.50 and 8.00 here
if (h === 7 && m >= 50)
console.log('Warning!');
}, 1000)
Now we can do more...
We can get the above routine to kick-start a timeout function which is going to be precise in the interval. It will trigger a countdown timer at the correct time and set alarm for another 24 hours.
var starter = setInterval(function(){
var d = new Date();
var h = d.getHours();
var m = d.getMinutes();
//Rough estimation for the time between 7.50 and 8.00 here
if (h === 7 && m >= 50)
setTimeout(timer24(), 1000 * 60 * 24)
}, 1000)
function timer24(){
//Warn every 10 seconds
var countdown = setInterval(function(){
console.log('Warning!');
var d = new Date();
var h = d.getHours();
if (h == 8)
clearInterval(countdown)
}, 10)
setTimeout(timer, 1000 * 60 * 24)
}
setInterval is used to repeat a callback function with a given time, setTimeout is used to run a callback after a specific amount of time. Since you need to create a counter, you can use setInterval here.
Note: If you want to display the users every sconds in 10 minutes, you may use 1000 as the interval timing value. But if you want to show every minutes in the 10 minute duration, then using 60 * 1000 as the interval timing value is better.
setInterval(function(){
var dateNow = new Date();
if(dateNow.getHours() >= 7 &&
dateNow.getMinutes >= 50 &&
dateNow.getHours < 8)
{
// if the alert box isn't displayed yet
// display it first.
// update the display.
}else{
// if the alert box is displayed
// hide it
}
}, 1000); // or 1000 * 60 for minute based display

Making a min:sec counter using javascript

I am trying to make a small question/answer quiz game using react, and I want to show a timer that counts down every second. Each game will last 10, 15, or 30 minutes at most, so I want to show a timer that updates every second in the bottom of the screen (in big font, of course!), something like 15:00, 14:59, 14:58, and so on until it hits 00:00.
So, given a start time such as 2016-04-25T08:00:00Z, and an end time after adding 15 min of 2016-04-25T08:15:00Z, I want to start the countdown.
My issue is that I am not understanding how to use setIntervals to keep calling my method to find the remaining time.
timeLeft = Math.round(timeLeft/1000) * 1000;
const timer = new Date(timeLeft);
return timer.getUTCMinutes() + ':' + timer.getUTCSeconds();
EDIT: You've edited your question. You will need the time padding, and the method below will be faster than what you are using, but to answer your question about setInterval:
First, define your function to run your timer and decrement each time it's called:
var timeLeft; // this is the time left
var elem; // DOM element where your timer text goes
var interval = null; // the interval pointer will be stored in this variable
function tick() {
timeLeft = Math.round(timeLeft / 1000) * 1000;
const timer = new Date(timeLeft);
var time = timer.getUTCMinutes() + ':' + timer.getUTCSeconds();
elem.innerHTML = time;
timeLeft -= 1000; // decrement one second
if (timeLeft < 0) {
clearInterval(interval);
}
}
interval = setInterval(tick, 1000);
OG Answer:
No, I do not believe there is a built-in way to display time differences.
Let's say you have two date objects:
var start = Date.now();
var end = Date.now() + 15 * 60 * 1000; // 15 minutes
Then you can subtract the two Date objects to get a number of milliseconds between them:
var diff = (end - start) / 1000; // difference in seconds
To get the number of minutes, you take diff and divide it by 60 and floor that result:
var minutes = Math.floor(diff / 60);
To get the number of seconds, you take the modulus to get the remainder after the minutes are removed:
var seconds = diff % 60;
But you want these two padded by zeros, so to do that, you convert to Strings and check if they are two characters long. If not, you prepend a zero:
// assumes num is a whole number
function pad2Digits(num) {
var str = num.toString();
if (str.length === 1) {
str = '0' + str;
}
return str;
}
var time = pad2Digits(minutes) + ':' + pad2Digits(seconds);
Now you have the time in minutes and seconds.

Stopwatch jQuery, calculate average and display

I am working on a stopwatch and for now it works, but I want that I can calculate the average of time people get. E.g. let's say I have 5 times in an array which looks like the following: scores = ["00:32:192", "00:30:126", "00:31:542", "00:25:236", "00:36:320"];. You may think now: What the hell is it? Well the times are in: minutes:seconds:milliseconds. The array is printed to the screen by using a for loop.
jQuery
var int,
ms=0,
s=0,
m=0;
$('#swatch').text("00:00:00");
function swatch(){
var startTime = new Date().getTime();
int = setInterval(function(){
var time = new Date().getTime();
var dif = time-startTime;
ms= dif%1000;
s = Math.floor(dif/1000)%60;
m = Math.floor(dif/1000/60)%60;
if(ms < 10) {
ms = '0'+ms;
}
if(s < 10) {
s = '0'+s;
}
if(m < 10) {
m = '0'+m;
}
$('#swatch').text(m+':'+s+':'+ ms);
},1);
}
var scores= [];
$(document).on('keydown', function(e){
var result = $('#swatch').text();
var i = parseInt(scores.length);
if(e.keyCode == 32 && !int){
swatch();
} else if (e.keyCode == 32){
clearInterval(int);
int=0;
scores.push(result);
$('#score ol').append('<li>' + scores[i] + '</li>');
if(scores.length >= 5) {
$('#ao5').html("ao5: 00:27:43");
$('#ao5').slideDown(500);
}
if (scores.length >= 12) {
$('#ao12').html("ao12: 00:27:43");
$('#ao12').slideDown(500);
}
}
});
In my code above this, you see this:
if(scores.length >= 5) {
$('#ao5').html("ao5: 00:27:43");
$('#ao5').slideDown(500);
}
if (scores.length >= 12) {
$('#ao12').html("ao12: 00:27:43");
$('#ao12').slideDown(500);
}
I want if the array has 5 different time values (as in the example above where I showed you the array format) it outputs the average on the screen. As you see I just filled it in for myself to picture it, but I want a function that calculates it. I am building this in jQuery because the timer worked better in here than in JS.
If some of you guys could give me an example and re-write my code with the function in it, that'd be great. I am really struggling with this for days to figure out how I can calculate an average of 5 and/or 12.
Thank you.
Note that the code I provide below doesn't rely on JQuery or any library directly. You feed it an array of 'time-strings', and it gives you back an average. You can use whatever library you choose to get that array of strings.
First, you need a utility function which breaks a time-string into it's component pieces:
var str_to_time = function(time_str) {
var pieces =time_str.split(':');
return {
minutes: parseInt(pieces[0], 10),
seconds: parseInt(pieces[1], 10),
milliseconds: parseInt(pieces[2], 10)
};
};
Now a function to convert an array of time-strings to an array of times:
var str_array_to_time_array = function(str_array) {
return str_array.map(str_to_time);
};
Lastly, a way to average all these values together:
var average_time = function(time_array) {
var minutes = 0;
var seconds = 0;
var milliseconds = 0;
for (var i = 0; i < time_array.length; i++) {
minutes += time_array[i].minutes;
seconds += time_array[i].seconds;
milliseconds += time_array[i].milliseconds;
}
minutes /= time_array.length;
seconds /= time_array.length;
milliseconds /= time_array.length;
// Minutes and seconds may be fractional. Carry the fractions down.
seconds += (minutes - Math.floor(minutes)) * 60;
minutes = Math.floor(minutes);
milliseconds += (seconds - Math.floor(seconds)) * 1000;
seconds = Math.floor(seconds);
milliseconds = Math.round(milliseconds);
// if milliseconds is >= 1000, add a second.
seconds += Math.floor(milliseconds / 1000);
milliseconds %= 1000;
// If seconds >= 60, add a minute.
minutes += Math.floor(seconds / 60);
seconds %= 60;
return {
minutes: minutes,
seconds: seconds,
milliseconds: milliseconds
};
};
Now you can call something like the following to get an average:
average_time(str_array_to_time_array(['33:23:354', '34:00:32']))
// Object {minutes: 33, seconds: 41, milliseconds: 693}

Jquery stopwatch with milliseconds (accurate)

I'm trying to create a stopwatch with miliseconds which is as accurate as possible.
Of course the browser/server/cpu or whatever will need more than 1 ms to execute the function and display the digit on the watch. So I thought i want to reset the ms to 0 each time a second goes up.
jQuery code looks like this.
(function($) {
$.fn.stopwatch = function() {
// The Element where the HTML code is added
var clock = $(this);
var timestamprunningms;
var timestampstartms;
var milliseconds = 0;
// Predefinition of the timestamprunningseconds variable
var timestamprunningseconds;
var display = clock.find("#display");
var time = clock.find("#time");
// Predefinition of the seconds variable
// Value 0 because it is used to define
// The timestampstartseconds variable in the click-event
var seconds = 0;
// Predefinition for the timestampstartseconds variable
var timestampstartseconds;
// Predefinition for the timer variable
var timer;
// Time Variables
var h = clock.find("#h");
var m = clock.find("#m");
var s = clock.find("#s");
var ms = clock.find("#ms");
// Button Variables
var resetlog = clock.find("#resetlog")
var showms = clock.find("#showms")
var hidems = clock.find("#hidems")
var start = clock.find("#start");
var pause = clock.find("#pause");
var reset = clock.find("#reset");
var log = clock.find("#log");
ms.hide();
resetlog.click(function (){
time.html("");
});
// Hides the pause and hidems Button
pause.hide();
hidems.hide();
// Triggered by clicking the start button
start.click(function() {
// Hides the start and shows the pause button
start.hide(),
pause.show(),
// Defines the value of timestampstartseconds or saves it
// if there is a value in seconds
timestampstartseconds = Math.round(new Date().getTime() / 1000) - seconds;
timestampstartms = new Date().getTime() - milliseconds;
timer = setInterval(do_time, 20);
});
// Triggered by clicking the pause button
pause.click(function() {
// Resets the interval in which the do_time function occurs
clearInterval(timer),
// Hides the pause and shows the start button
pause.hide(),
start.show(),
timer = 0;
});
// Triggered by clicking the reset button
reset.click(function() {
// Resets the interval in which the do_time function occurs
clearInterval(timer),
// Resets the value of the display
h.html("00"),
m.html("00"),
s.html("00"),
ms.html("000")
// Hides the pause and shows the start button
pause.hide(),
start.show();
seconds = 0;
});
log.click(function() {
time.append("<li>" + display.text() + "</li>");
});
// The function for calculating the seconds/minutes/hours
showms.click(function() {
showms.hide();
hidems.show();
ms.show();
});
hidems.click(function() {
hidems.hide();
showms.show();
ms.hide();
});
function do_time() {
// Timestamp that refreshes everytime the function is executed
timestamprunningseconds = Math.round(new Date().getTime() / 1000);
timestamprunningms = new Date().getTime();
// The actual seconds that are going to be displayed
milliseconds = timestamprunningms - timestampstartms;
seconds = timestamprunningseconds - timestampstartseconds;
// Value of the display
var hour = parseFloat(h.text());
var minute = parseFloat(m.text());
if (milliseconds > 999) {
milliseconds = 0;
timestampstartms = new Date().getTime();
}
// Reset seconds display and add a minute every time 60 seconds pass
if (seconds > 59) {
seconds = 0;
timestampstartseconds = Math.round(new Date().getTime() / 1000);
minute++;
}
// Reset minute display and add an hour every time 60 minutes pass
if (minute > 59) {
minute = 0;
hour++;
}
// Display value
h.html("0".substring(hour >= 10) + hour);
m.html("0".substring(minute >= 10) + minute);
s.html("0".substring(seconds >= 10) + seconds.toString());
ms.html(":" + "0".substring(milliseconds >= 100) +"0".substring(milliseconds >= 10) + milliseconds.toString());
};
};
})(jQuery);
As I already said, my goal is to reset the millisecond timer every time a second goes up. (the seconds are accurate, the milliseconds aren't).
would that be something like this?:
while (seconds++) {
milliseconds = 0;
timestampstartms = new Date().getTime();
}
I'm really new to javascript/jQuery and programming in general so it would be very nice if you could help me with this problem and maybe give a little feedback so I can improve.
Ok I found a solution: i just added a variable which is like a timestamp of the current second. It has a default value of 0 and goes 1 up if the seconds that is used in the display is greater than the second timestamp.
looks a bit like this: var secondnow = 0; (on top of the jQuery function)
and this is how it's used
if (seconds > secondnow) {
milliseconds = 0;
secondnow++;
timestampstartms = new Date().getTime();
console.log(secondnow);
}
(in the function do_time)

Categories