Multiple timers on a page - javascript

I've been given a task to display multiple timers on a page in a table. The start values for these timers are stored in a database and loaded into the view when the page loads.
I initially designed this as a single timer. In that version, using the clearInterval() method to stop the timer from counting down past 0:00 works. With the multiple timers, it does not.
There's no way for me to anticipate how many records are going to display in the table.
The single counter variable was how I implemented this when there was only one timer. That seems to still work to start the countdown process, but doesn't stop it as expected when the clearInterval(counter) is called.
var counter;
// NOTE: Does not support days at this time
// Ex: StartTimer(5, 'm', 'timer') for Five Minutes
// Ex: StartTimer(5, 'h', 'timer') for Five Hours
function StartCountdownTimer(timeDistance, timeMeasurement, timerCallback) {
// Add timeDistance in specified measurement to current time
var countDownDate = moment().add(timeDistance, timeMeasurement).toDate();
var timeRemaining;
counter = setInterval(function () {
// Get Current Time
var now = new Date().getTime();
// Find the distance between now an the count down date
var distance = countDownDate - now;
let duration = moment.duration(distance * 1000, "milliseconds");
let hours = duration.hours();
let minutes = duration.minutes();
let seconds = duration.seconds();
if (minutes < 10 && hours && hours > 0) {
minutes = "0" + minutes;
}
if (seconds < 10) {
seconds = "0" + seconds;
}
// If the count down is finished clear the counter interval.
if (distance < 0) {
clearInterval(counter);
}
else {
timerCallback(hours, minutes, seconds);
}
}, 1000);
}
I would guess that the clearInterval() is not working because there are multiple timers on the page, but I'm not sure of the best way to load multiple variables and assign them to their own setInterval() function to then leverage when doing the clearInterval() later.
This is a separate JS file that is called by the HTML in the $(document).ready() function.
Any ideas on how to get this clearInterval() to work with multiple timers on a page?

Put the various intervals in an object, with a counter variable that increments every time you assign an interval. Then use the counter as the key and assign its value to the interval.

Related

is it possible to fix one time using momentjs?

I am trying to fix one time and that time is current time + 10 minutes and i wanted to use a condition where when the current time is equal to the set time it will run my logic is it possible?
I have tried using moment but not able to completely solve the problem
here is my tried solution
const currentTime = momentTz().tz("Asia/Kolkata");
console.log(currentTime.valueOf());
const notificationTime = momentTz()
.tz("Asia/Kolkata")
.add(10, "minutes")
.valueOf();
// console.log(currentTime);
console.log(notificationTime);
// i want to run in this way
if(notificationTime === currentTime.valueof())
{
//notiifcation send}
How will code come to know to run script after some time?
You should use setTimeout for this
Like
setTimeout(() => {
// your code which has to be executed after 10 minutes
}, 1000 * 60 * 10)
Or if you want check after some intervals you can use setInterval
Like following code will check for condition after every minute
var myInterval = setInterval(() => {
const currentTime = momentTz().tz("Asia/Kolkata");
if (notificationTime <= currentTime.valueof()) {
//notiifcation send
clearInterval(myInterval)
}
}, 1000 * 60)

Reload html page at every tenth minute

I am trying to update a web-page at every tenth minute 7:40...7:50, etc. How do I do this?
Here is my code:
<body onload="checkTime()">
function checkTime(){
var unixTime = Date.now() / 1000;
var partTenMinuteTime = unixTime%600;
var time = unixTime - partTenMinuteTime + 600;
var difference = (time-unixTime)*10000;
console.log(difference);
setInterval(location.reload(),15000)
}
This is all I have, everything else I have tried does not work. I am using location.reload();
My problem is where this function gets called and how to implement it.
Here you can get nearest 10th min
let getRoundedDate = (minutes, d=new Date()) => {
let ms = 1000 * 60 * minutes; // convert minutes to ms
let roundedDate = new Date(Math.round(d.getTime() / ms) * ms);
return roundedDate
}
console.log(getRoundedDate(10))
Now you can use setInterval or in recursive setTimeout
You can get the minutes of the current hour and check how many minutes there are until the next 10-minute mark and use setTimeout. Your updatePage method should also continue to use call itself with setTimeout, if you are using AJAX to refresh the page (which makes more sense than reloading).
function updatePage(){
//update page
setTimeout(updatePage, 10 * 60 * 1000);
}
const now = new Date;
const nextDate = new Date;
nextDate.setFullYear(now.getFullYear());
nextDate.setDate(now.getDate());
nextDate.setMonth(now.getMonth());
nextDate.setHours(now.getHours());
nextDate.setMinutes(Math.ceil(now.getMinutes()/10)*10);
setTimeout(updatePage, nextDate - now);
You were very close with the solution in your question.
A couple of things to note:
You don't need setInterval(), but can use setTimeout() instead. After the page is reloaded, you will get a new timeout.
The callback you pass to setInterval() or setTimeout() needs to be a function and not a function call. If you include a function call, it will be executed immediately and not wait for the timeout or interval.
There is no need to create additional intervals to be able to correctly determine the 10 minute mark, as proposed in other answers to this question. You can correctly determine the correct time to call the reload action by doing the calculation you had in your question.
I'm aware that there are situations where you have too little control over the server code to be able to convert to AJAX, but if possible AJAX or websocket solutions should be preferred over reloading the page.
function reloadAfter(minutes) {
const millisToWait = minutes * 60 * 1000;
const millisLeft = millisToWait - (Date.now() % millisToWait);
setTimeout(() => location.reload(), millisLeft);
}
addEventListener('load', () => reloadAfter(10));
Why reload the page at all? Just use AJAX to query what you need. Here's code you could use to do your AJAX query, or reload the page... the later being a bad practice:
function onTenMin(func){
const m = 600000;
let i = setTimeout(()=>{
func(i); i = setInterval(()=>{
func(i);
}, m);
}, m-Date.now()%m);
}
addEventListener('load', ()=>{
onTenMin(interval=>{ // if you want you can pass the interval here
const dt = new Date;
console.log(dt.toString());
});
}); // end load
Just pass the function you want to onTenMin.
What's happening here?
Date.now() gives you milliseconds since January 1, 1970, 00:00:00 UTC. 600000 milliseconds is 10 minutes. % is the remainder operator, so it gives you the milliseconds remaining after division of the 600000. 600000 minus that remainder gives you how many more milliseconds until the next ten minute time. When that timeout happens it executes the function you pass to func then sets an interval which executes every 600000 milliseconds, passing the interval to func.
You can use a meta refresh instead don't burden the engine with timers
<meta http-equiv="refresh" content="600">
10 minutes = 600 seconds, so... This would automatically refresh your page every 10 minutes exactly.
Update
Every Exact 10th Minute Of An Hour
var tick = 10*60*1000,
tock = tick - Date.now() % tick;
setTimeout( "location.reload()", tock );
var tick = 10 * 60 * 1000,
tock = tick - Date.now() % tick;
setTimeout("location.reload()", tock);
//-----show something on the page----
with(new Date(tock))
document.write("Reloading in: " +
getMinutes() + " min, " +
getSeconds() + " sec, " +
getMilliseconds() + " mil."
);

Timer is resetting on refresh how to avoid that?

this is my java-script code which is resetting on refreshing how to avoid that
<script>
//define your time in second
var c=120;
var t;
timedCount();
function timedCount()
{
var hours = parseInt( c / 3600 ) % 24;
var minutes = parseInt( c / 60 ) % 60;
var seconds = c % 60;
var result = (hours < 10 ? "0" + hours : hours) + ":" + (minutes < 10 ? "0" + minutes : minutes) + ":" + (seconds < 10 ? "0" + seconds : seconds);
document.getElementById("timer").innerHTML=result;
if(c == 0 )
{
//setConfirmUnload(false);
//$("#quiz_form").submit();
window.location="result.php?td=$tid";
}
c = c - 1;
t = setTimeout(function()
{
timedCount()
},
1000);
}
</script>
Whenever a page is readloaded, the entire context of the old page is destroyed and an entirely new context is created. You can't keep a timer from one page load running on the next page load.
If you need to save some state from one page load to the next and then in the next page load examine that state and decide exactly how to set up the initial page to match what was previously going on, then you can save state between page loads in either HTML5 local storage or in a cookie.
The other possibility is to NOT reload your page and instead update the contents of the page dynamically using ajax and javascript. That way your existing timer would just keep running because there would be no page reload at all.
If all you're trying to do with your timer is show how much time is left in some countdown, you can set the countdown zero time into HTML5 local storage and when the reloaded page loads, it can check the time set in local storage and start the countdown timer to match the time it was previously set for.
Use cookie, or if HTML5 then local/session storage to save state.
HTML
Save Current Time |
Retrieve Saved Time
<div id="result"></div>
JAVASCRIPT
function SaveTime(){
var date = new Date();
var timeObj = { sec:date.getSeconds(), min:date.getMinutes(), hr:date.getHours() };
localStorage.setItem("timeObj", JSON.stringify(timeObj));
$('#result').append(JSON.stringify(timeObj)+' -- > Saved<br />' );
}
function retrieveTime(){
var timeObj = JSON.parse(localStorage.getItem("timeObj"));
//You have the time with you now
//You have the time with you now
$('#result').append(timeObj.hr+':'+timeObj.min+':'+timeObj.sec+' --> Retrieved<br />');
}
Its just a basic example to save timer in local storage on click. Modify it and call the javascript function in timer regularly.

"infinite" setinterval function "timing out"

having a slightly weird issue that I cant figure out. Ive set up a javascript timer, all it does is repeats an interval every second that checks the difference between 2 dates and displays the results. All seems fine, however when leaving the browser open for several minutes (not touching it.. literally walking away for a while), it seems to "time out" and stop functioning. No console error messages or anything, the code just stops executing.. Was wondering if anyone had any idea what could be causing this? Is my code the issue or is this a built in browser function to stop js functions if there is no input from the user on a page for a certain time?
edit sorry should mention this timer is set to run for around 40 days at the moment so it will never realistically meet the clearinterval statement in a user session. The future date variable im adding to the function is a dynamic unix timestamp from PHP for a date which is roughly 40 days in future. Currently set to 1444761301.88
function MModeTimer(futureDate) {
zIntervalActive = true;
var currentTime = new Date().getTime() / 1000;
var timeRemaining = futureDate - currentTime;
var minute = 60;
var hour = 60 * 60;
var day = 60 * 60 * 24;
var zDays = Math.floor(timeRemaining / day);
var zHours = Math.floor((timeRemaining - zDays * day) / hour);
var zMinutes = Math.floor((timeRemaining - zDays * day - zHours * hour) / minute);
var zSeconds = Math.floor((timeRemaining - zDays * day - zHours * hour - zMinutes * minute));
if (zSeconds <= 0 && zMinutes <= 0) {
console.log("timer in negative");
// timer at zero
clearInterval(zTimeInterval);
} else {
if (futureDate > currentTime) {
console.log("timer interval running");
// changes html as part of function
}
}
}
zTimeInterval = setInterval(function() {
MModeTimer(zNewTime)
}, 1000);
This line:
clearInterval(zTimeInterval);
Is clearing the interval when the condition:
if (zSeconds <= 0 && zMinutes <= 0) {
Is met.
And as per the log you've wrote inside, that would be wrong. You are checking that zSeconds and zMinues are less or equal to 0. So when both are 0, the interval will be cleared.
Edit
As per your edits and explanations, may I suggest adding a console log that i'ts not inside any condition?:
function MModeTimer(futureDate) {
console.log('running');
//... rest of your code
That way you can make sure if the interval is running, maybe your conditions are not being TRUE after a while and you won't see any log, but the interval would be still running.

Performing an operation days or months in the future

I'm trying to figure out the best way to perform a task, e.g. send an email to a user, in the future.
My idea is to store (in a database along with users data) when the email needs to be sent, and on a daily basis check what users need emails sent, and use Meteor's Timer functions.
// 7 hours in millisec.
Meteor.setTimeout( function() {
Meteor.call( "sendReminderEmail", ... );
}, 2.52e+7 );
The problem that I see is having too many timers set up, and hindering performance. What is a good solution?
Edit: Basically my use case includes the user creating an event, which they set as a long term event or short term(based on days, weeks, or months), and they receive a follow-up on that event depending on the duration.
I guess I could check every hour, but that seems like a problem with equal cost. Is there a Meteor specific way to do this? Or just a better concept?
Edit2: Ok, I've realized that accurracy isn't that important for my problem, so I'm thinking of setting one timer per timezone, which would send bulk emails. If the user has a long term event and their reminder is this week, than send it now. Basically it depends on duration of event and timezone of user.
So my updated question is, how do I run something on a daily basis, with my problem in mind?
Let's say you want to execute a code at 9am today and now is 8am, you could create a timeout to match the minutes in the targeted time and then create a interval of 1 hour and at each execution check if the time is 9am, if it's, execute.
in this small scale example, I'm executing executeMe() when the clock shows 9 seconds:
Live Test: http://jsbin.com/ikulok/4/edit
<body>
Last run: <span id="time"></span><br>
Next execution: <span id="target"></span>
<script type="text/javascript">
function executeMe(){
alert("9 seconds!");
}
var timeout = null;
var interval = null;
function timer(){
var now = new Date();
document.getElementById('time').innerHTML = now;
document.getElementById('target').innerHTML = new Date(now.getTime()+ 1000);
//console.log("timer()", now);
if(now.getSeconds() == 9)
setTimeout("executeMe();",1); // async
if(interval == null)
interval = setInterval("timer()",1000);
}
var now = new Date();
var target = new Date(now.getFullYear(),now.getMonth(),now.getDate(),now.getHours(),now.getMinutes(),now.getSeconds()+1,0);
//console.log("now", now);
//console.log("target", target);
//console.log("diff", target.getTime() - now.getTime());
document.getElementById('target').innerHTML = target;
timeout = setTimeout("timer()", target.getTime() - now.getTime() );
</script>
If you want to run the timer() every hour instead of every second, just adjust the target and the setInterval() and of course your conditions
Live Test: http://jsbin.com/ikulok/3/edit
<body>
Last run: <span id="time"></span><br>
Next execution: <span id="target"></span>
<script type="text/javascript">
function executeMe(){
alert("1:20am!");
}
var timeout = null;
var interval = null;
function timer(){
var now = new Date();
document.getElementById('time').innerHTML = now;
document.getElementById('target').innerHTML = new Date(now.getTime()+ 1*60*60*1000);
//console.log("timer()", now);
if(now.getHour() == 1)
setTimeout("executeMe();", 20*60*1000); // !!!! this will execute at 1:20am
if(interval == null)
interval = setInterval("timer()",1*60*60*1000); // !!!! repeat every hour
}
var now = new Date();
// !!!! targeting next exact hour
var target = new Date(now.getFullYear(),now.getMonth(),now.getDate(),now.getHours(),now.getMinutes()+1,0,0);
//console.log("now", now);
//console.log("target", target);
//console.log("diff", target.getTime() - now.getTime());
document.getElementById('target').innerHTML = target;
timeout = setTimeout("timer()", target.getTime() - now.getTime() );
</script>
</body>

Categories

Resources