Why does my javascript clock crash after a minute? - javascript

I have double checked and tested on jshint for syntax errors and such. I have also compared my code to others who created the same clock, but did not see any differences that would cause my clock to crash. I do not understand what is causing this problem.
$(document).ready(function(){
function displayTime() {
var currentTime = new Date();
var hours = currentTime.getHours();
var minutes = currentTime.getMinutes();
var seconds = currentTime.getSeconds();
var miridiem = "AM";
var clockDiv = document.getElementById('clock');
if(seconds < 10) {
seconds = "0" + seconds
}
if(minutes < 10) {
minutes = "0" + minutes
}
if (hours > 12) {
hours = hours - 12
miridiem = "PM"
}
if (hours === 0) {
hours = 12
}
clockDiv.textContent = hours + ":" + minutes + ":" + seconds + " " + miridiem;
setInterval(displayTime, 1000);
}
displayTime();
});
<body>
<div id="clock"></div>
<script src="https://code.jquery.com/jquery-3.0.0.min.js" integrity="sha256-JmvOoLtYsmqlsWxa7mDSLMwa6dZ9rrIdtrrVYRnDRH0=" crossorigin="anonymous"></script>
</body>
Warning: snippet will eat your memory. Don't forget to stop it.
https://jsfiddle.net/9cp9m43h/

You're just misunderstanding the usage of setInterval and setTimeout.
As some commenters mentioned, you could just change your current implementation to use setTimeout and it would function pretty well.
However, in my opinion, the best solution would be to change the way your code works, so that setInterval works correctly:
$(document).ready(function(){
function displayTime() {
var currentTime = new Date();
var hours = currentTime.getHours();
var minutes = currentTime.getMinutes();
var seconds = currentTime.getSeconds();
var miridiem = "AM";
var clockDiv = document.getElementById('clock');
if(seconds < 10) {
seconds = "0" + seconds
}
if(minutes < 10) {
minutes = "0" + minutes
}
if (hours > 12) {
hours = hours - 12
miridiem = "PM"
}
if (hours === 0) {
hours = 12
}
clockDiv.textContent = hours + ":" + minutes + ":" + seconds + " " + miridiem;
}
displayTime();
setInterval(displayTime, 1000);
});
I feel this is better because:
this is what setInterval was designed for: performing the same action over and over at a specific interval.
calling setTimeout manually to reset the timer leaves you open to some clock skew; if it takes a millisecond for your displayTime to run before it sets the timeout, then after 1000 seconds you're probably going to be about 1 second off.
a function called displayTime() sounds like all it's doing is displaying the time--there's nothing to hint that it's also creating a long-term side-effect. The separation of concerns feels better if the timer is set outside of that method.
The effects of displayTime() are easier to test independently when it's not creating asynchronous side-effects.

I think your setInterval() is in the wrong place. You placed it inside the function, which is registering 60 interval monitors per minute so the memory is crashing. If you wanted to trigger the next timeout after the function has been called, you can do that using setTimeout(), within the displayTime() function. But if you do setInterval(), you want that to be called at the same level that your initial displayTime() function is called.
See my fiddle: https://jsfiddle.net/9cp9m43h/3/

every time displayTime() is called it starts a new Interval that calls displayTime() every second.
Therefore every second the function is called twice as often as the time before. After 60 Seconds this is Math.pow(2, 60) //=> 1152921504606847000 times.
Hmm, i'm having a hard time figuring out how it crashed with the setInterval() within the displayTime() function, but working completely fine outside the function.
Because in this case displayTime() is not calling itself not even a roundtrip over setInterval. So it stays a single Interval, and therefore a single function-call every second.

Related

Countdown server side best practices

Problem
I have a countdown that is server side and needs to be shown on the client. First i made it using socket.io basically emitting it every 100 milliseconds. Now i really like this but i fear there might be significant performance downgrade to instead just emit a signal and having the client make the countdown but this brings another problem which is not being able to see the countdown value until it resets. Is emitting every 100ms really that bad of a practice or is this ok ?
Edit
I need it server side because of authentication and consistency for all users loop is small 40 secs followed by a 10 sec pause. I need to know if users have performed the action in that period
Honestly, I would recommend doing it by the client because it's easiest and better even if they had some type of disconnection from the server
function msToTime(duration) {
var seconds = parseInt((duration/1000)%60),minutes = parseInt((duration/(1000*60))%60),hours = parseInt((duration/(1000*60*60))%24),days = parseInt(duration/(1000*60*60*24));
var hoursDays = parseInt(days*24);
hours += hoursDays;
hours = (hours < 10) ? "0" + hours : hours;
minutes = (minutes < 10) ? "0" + minutes : minutes;
seconds = (seconds < 10) ? "0" + seconds : seconds;
return hours + ":" + minutes + ":" + seconds;
}
function startCountdown(){
setInterval(function(){
var a = new Date().getTime();
var now = new Date();
var b = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 24, 0, 0, 0).getTime();
document.getElementsByClassName("text")[0].innerHTML= msToTime(b-a);
},0);
}
<input onclick="startCountdown()" type="submit">
<p class="text" ></p>
Function From here: https://stackoverflow.com/a/19700358/14746601

JavaScript clock not showing current time on mobile devices

I got this JavaScript Code to display the current time on my website, works perfectly for desktop but it doesn't work on mobile devices
It freezes on the time when the user visits the page
Is it any way to make this possible? Something like refresh the script every sec to show the current time or any other solution?
document.getElementById("clock").innerHTML = GetTime();
function GetTime(){
var d = new Date();
var nhour = d.getHours(),nmin=d.getMinutes();
if (nmin<=9) {
nmin = "0" + nmin
}
return nhour+":"+nmin+"";
}
<span id="clock"></span>
Your help is really appreciated!
EDIT: Thanks to mdickin I realized the clock doesn't update even in desktop. So the entire code has something wrong.
Yes you could use a setInterval, which runs a function at regular intervals (in milliseconds).
function setTime()
{
document.getElementById("clock").innerHTML = GetTime();
}
setInterval(setTime,1000);
You could change the number of milliseconds to suit, depending on how accurate you want to be...but I doubt you would need to worry about being more than a second out either way.
Here's a link with more information about setInterval and setTimeout
Use setInterval to run your GetTime() function every second:
document.getElementById("clock").innerHTML = GetTime();
function GetTime(){
var d = new Date();
var nhour = d.getHours(),nmin=d.getMinutes();
if (nmin<=9) {
nmin = "0" + nmin
}
return nhour+":"+nmin+"";
}
setInterval(GetTime, 1000); // run GetTime every 1000ms
<span id="clock"></span>
Here is a simple program that I wrote in codepen to create a live JS timer. Basically all you need to do is call the function inside a setTimeout function and provide the frequency in milliseconds.
function startTimer() {
var today = new Date();
var hours = today.getHours();
var mins = today.getMinutes();
var sec = today.getSeconds();
mins = checkTime(mins);
sec = checkTime(sec);
document.getElementById('timer').innerHTML =
hours + ":" + mins + ":" + sec;
var t = setTimeout(startTimer, 100);
}
function checkTime(i) {
if (i < 10) {
i = "0" + i
};
return i;
}
<body onLoad="startTimer()">
<div id="timer"></div>
</body>
Here is the link to my codepen

How to add milliseconds to this javascript reverse count down timer counter

numberOfSeconds=1*60,
r=document.getElementById('clock');
var t = setInterval(function(){
numberOfSeconds--;
var minutes=Math.floor(numberOfSeconds/60),seconds=(numberOfSeconds%60)+'';
r.textContent='Registration closes in '+minutes+':'+(seconds.length>1?'':'0')+seconds;
if (numberOfSeconds <= 0) {
clearInterval(t);
alert('boom');
}
},1000);
html section
<div id="clock"></div>
how i can add milliseconds to this reverse count down timer/counter script.
i want it like 00:00:00 <== milliseconds in last.
}},1000 / 20);
However above little change in last of script made seconds into milliseconds but i can't figure out how i can adjust it with seconds like MM:SS:MS 00:00:00
Any Help will be appreciated..!
That setInterval will have to be set to 1 (ms), if you need to see the milliseconds. 1000ms = 1s. So I believe MM:SS:MS would look more like 00:00:000.
I do not think it's possible. i did a test and the results show that js cannot be as fast to set 1millisecond to setInterval. setting it to 1ms - 15ms will output the same results.
normaly the code below should work the way you wanted.
var m = 60*1000, r = document.getElementById("clock");
var t = setInterval(function () {
m--;
var min = Math.floor(m / 60000),
sec = Math.floor((m % 60000) / 1000);
mil = (m % 60000) % 1000; r.innerHTML = min + ":" + sec + ":" + mil;}, 1)
Maybe the problem comes from my computer (maybe it is slow).
if you ever want the test script, tell it in comment so i will give it to you in order you'll test it by yourself

JavaScript Freezes Browser

I'm trying to make a countdown timer for each row of a table based on a hidden field containing the ammount of seconds to finish. Here is what I have done so far:
function countdownProcedure() {
var interval = 1000;
var i = 0;
var seconds;
$(".rfqTbl tr").each(function() {
if(i > 0) {
seconds = $(this).find("#sqbTimestamp").text();
var days = Math.floor(seconds / (60*60*24));
seconds -= days * 60 * 60 * 24;
var hours = Math.floor(seconds / (60*60));
seconds -= hours * 60 * 60;
var minutes = Math.floor(seconds / 60);
seconds -= minutes * 60;
if(days < 1) { days=""; }
$(this).find("#countDown").html(days + "<pre> Days</pre> " + hours + "<pre>:</pre>" + minutes + "<pre>:</pre>" + seconds);
if(days > 1) {
$(this).find("#countDown").css({
'color':'#2A7F15',
'font-weight':'bold'
});
};
if(days < 1) {
$(this).find('#countDown').css('color','red');
$(this).find('#countDown pre:nth-of-type(1)').css('display','none');
}
if(seconds < 10) {
$(this).find("#countDown").append(" ");
};
if(minutes < 60){ interval = 1000; };
}
i++;
});
setInterval(countdownProcedure,interval);
};
However, my problem is that I'm trying to get this function to run (realistically every second or 30) so that the time shown would update and hence 'countdown'. The problem I am having is in firefox and safari the browsers are just hanging after the first countdown and chrome is doing nothing (I guess it has a safe guard to prevent it from hanging).
Any help would be much appreciated!
You are running a multitude of setInterval() calls, so the event queue gets crowded with your function.
I think, what you mean is more like setTimeout() at the end of your function.
function countdownProcedure(){
// all your logic
setTimeout(countdownProcedure,interval);
};
The difference is, that setInterval() will run your code every x seconds, until you tell it to stop.
setTimeout() on the other hand, just runs your code once after x seconds.
Change all ids for clases Ex: #sqbTimestamp for .sqbTimestamp
in an HTML document, should exists only 1 element with some id, if you set multiple elements with same id, unexpected results (as browser hanging) can occurrs.
Also, you are setting days="" and then do the following compare if (days > 1)
I think your algorithm is wrong. You are recursively setting intervals which are calling themselves every time and setting new intervals and so on...
You must change your algorithm a bit to get it clean.

Count-Up Timer on each page load from 0

I want to implement a count-up timer JS code that starts counting at each load page from 0. The code which I've now is like this:
var secondsTotal = 0;
setInterval(function() {
++secondsTotal;
var minutes = Math.floor(secondsTotal / 60);
var seconds = Math.floor(secondsTotal) % 60;
var milliseconds = Math.floor(secondsTotal) % 1000;
document.getElementById('counter').innerHTML = minutes + ":" + seconds + "." + milliseconds;
}, 1000);
The output format should be: 00:00.0
mm:ss.ms
So, how to output the result like above format (minutes and seconds should be exactly printed in two digits format)?
If you want to do it per-page, you're almost there. Right now, your code does not allow you to track milliseconds, as your setInterval runs every second. What I would recommend instead is something like this:
(function() {
var counter = 0,
cDisplay = document.getElementById("counter");
format = function(t) {
var minutes = Math.floor(t/600),
seconds = Math.floor( (t/10) % 60);
minutes = (minutes < 10) ? "0" + minutes.toString() : minutes.toString();
seconds = (seconds < 10) ? "0" + seconds.toString() : seconds.toString();
cDisplay.innerHTML = minutes + ":" + seconds + "." + Math.floor(t % 10);
};
setInterval(function() {
counter++;
format(counter);
},100);
})();
This does a couple of things to allow your code to run 10 times per second:
The output element, #counter, is cached and not retrieved every iteration
The formatting is kept to arithmetic operations only - modulo and division.
This now also adds leading zeroes.
If you would like to keep this counter running page-per-page, consider using document.cookies to pass the final value from page to page.
Fiddle
This serves as a good first version. However, you may want to:
Pause/re-start your timer
Reset your timer
Have multiple timers
For this reason, I will add a slightly more complex form of the above code, which will allow you to manage multiple timers. This will make use of a few OO concepts. We will use a TimerManager object to "host" our timers, and each Timer object will have a link to the manager.
The reason for this is because every timer will depend on the same setInterval() by doing it this way, rather than to have multiple setInterval() calls. This allows you to cut down on wasted clock cycles.
More on this in about 5 minutes!
Counting seconds that way isn't guaranteed to be accurate. The setInterval method can drift on you based upon the JS engine's ability to complete its other tasks. Not sure what your use case is, such as how long you expect to count up, but it's worth taking note of. See Will setInterval drift? for a detailed explanation.
I'd recommend you check out the momentjs plugin # http://momentjs.com/ and update your code to something like the following
var startTime = moment();
var el = document.getElementById('counter');
setInterval(function() {
var ms = moment().diff(startTime),
min = moment.duration(ms).minutes(),
sec = moment.duration(ms).seconds();
ms = moment.duration(ms).milliseconds();
min = (min < 10) ? "0" + min.toString() : min.toString();
sec = (sec < 10) ? "0" + sec.toString() : sec.toString();
ms = ms.toString().substring(0,2); // change this if you want to expand ms counter display
el.innerHtml = min + ":" + sec + "." + ms;
}, 50);
You're free to update the interval, and your milliseconds display without adjusting your calculations.

Categories

Resources