Javascript countdown - not counting down - javascript

I have a countdown script that gets the live time and subtracts it from a set time. It all works apart from the fact that it doesn't update unless you refresh your page. The setInterval at the bottom of my function instructs the function to run every one second, but it doesn't seem to be doing that...
Can anybody help?
Here is my jsfiddle: http://jsfiddle.net/4yMZy/

Each time cCountDown runs, its is calculating the time left like so:
nDates = new Date(datetime);
xDay = new Date("Fri, 26 May 2012 16:34:00 +0000");
timeLeft = (xDay - nDates);
The value of datetime there never changes from one run to another. So cCountDown is constantly running, but is always comparing the difference between the same two dates. Since the same two dates are used, the difference is always the same, so you do not see any countdown occur.
You could change nDates = new Date(datetime); to nDates = new Date(); and it will start counting down, but I am not sure why you are getting datetime from some server in the first place.

There are some other issues with your code as well. You should run it through jslint or jshint.
If changed your code to http://jsfiddle.net/4yMZy/7/
So it fetches the time and updates the seconds according to the set interval.
Edit:
jsfiddle actually provides a button for that on the top.

Related

JavaScript function to run everyday at 6:30pm EST

I have written a JavaScript function that I simply copy paste into a browser console and runs, all works great and is working exactly as I want it to.
Looks like:
function test(d) {
// ....
}
test(num);
I'm looking to wrap this function with kind of like a "while" statement. Please do keep in mind I'm not the greatest with JavaScript, yet.
Basically, What I'm looking for is while its NOT 6:30PM EST... keep waiting and check again. The second it hits 6:30 PM EST, execute the script.
Can anyone help me with what the syntax would look like? I found a lot on Stack Overflow but the syntax isn't really making sense to me.
Any help would be greatly appreciated.
Okay, a couple of notes. If you're not required to run a script in the browser itself but simply run some JavaScript at specific intervals you should checkout some schedulers like cron and more specifically for JavaScript - node-cron.
A solution which revolves around checking "is it time, is it time,..." each second or so in a loop is a pretty bad way to do it.
It is highly wasteful and poorly performant.
It will block your script execution so you have to execute it in a separate process like a web worker.
The simplest way, without using any dependencies is to schedule your work manually using a combination of setTimeout and setInterval. Here is a pretty basic and unpolished solution which should get you going.
const msInSecond = 1000;
const msInMinute = 60 * msInSecond;
const msInHour = 60 * msInMinute;
const msInDay = 24 * msInHour;
const desiredTimeInHoursInUTC = 18; // fill out your desired hour in UTC!
const desiredTimeInMinutesInUTC = 30; // fill out your desired minutes in UTC!
const desiredTimeInSecondsInUTC = 0; // fill out your desired seconds in UTC!
const currentDate = new Date();
const controlDate = new Date(currentDate.getUTCFullYear(), currentDate.getUTCMonth(), currentDate.getUTCDate(), desiredTimeInHoursInUTC, desiredTimeInMinutesInUTC, desiredTimeInSecondsInUTC);
let desiredDate;
if (currentDate.getTime() <= controlDate.getTime()) {
desiredDate = controlDate;
}
else {
desiredDate = new Date(controlDate.getTime() + msInDay);
}
const msDelta = desiredDate.getTime() - currentDate.getTime();
setTimeout(setupInterval, msDelta);
function setupInterval() {
actualJob();
setInterval(actualJob, msInDay);
}
function actualJob() {
console.log('test');
}
In short, it calculates the difference between the current time and the next possible upcoming time slot for execution. Then, we use this time difference to execute the desired task and further schedule executions on every 24h after that.
You need to provide values for desiredTimeInHoursInUTC, desiredTimeInMinutesInUTC and desiredTimeInSecondsInUTC. All of them should be in UTC (the normal difference between EST and UTC is -4 or in other words - (hour EST - hour UTC = -4). You can (and actually should) improve this solution to handle timezones and the time difference calculations in general more elegantly.
A caveat here is that it won't handle daylight saving for you so you should keep that in mind. You can tackle this easily by using a dedicated library like moment.js. Also, the code is simple and in this version doesn't support cases like skipping specific days and such. You can always extend it to handle those, though.
Lastly, every time you restart the script, it will schedule your function execution times properly so you don't need to keep your tab open at all times. As an added benefit, the solution is quite performant as it doesn't do checks continuously if the time for execution has come but schedules everything in advance and doesn't do any more checks after that.

Browser seems to cache DateTime

I realized that a change in system time is not immediately reflected in javascript, event if I use a new Date object. It is only updated every minute.
var fakeElapsed = 0;
$(document).ready(function(){
var oldTime = 0;
function fakeTimeLoop(time){
fakeElapsed+=(time-oldTime);
oldTime = time;
$("div").html(fakeElapsed);
}
var clock = new Date();
var start = clock.getTime();
oldTime = clock.getTime();
setInterval(function(){
var clock2 = new Date();
var end = clock2.getTime();
var elapsed = end-start;
if(elapsed%5===0){
fakeTimeLoop(end);
}},
1
);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div></div>
</body>
Time code, if you would turn time forward (or backwards), it takes a minute to change the time elapsed.
Is there anyway to update to the system time every second?
Edit: for those who are confused, a change in system is not reflected immediately on Chrome and Opera, but on IE and Mozzila, it is immediately reflected, I assume its order to avoid expensive system calls every time it needs to build a new Date object.
What I am looking for: is that anyway to get the current system time in chrome/opera or detect a change in system time immediately?
It's not exactly clear to me what you're trying to accomplish, but your setInterval is programmed to execute every millisecond (the second parameter is in milliseconds), but browsers treat any value less than 10 as equal to 10. Even with that restriction, the timing isn't guaranteed to be exact, so the function may well execute every 11, 12, 13, etc. milliseconds.
When you change your computer date/time and refresh the web page, new Date() will not return correct date/time. After 20-25 seconds it will return correct time. Probably it is a browsers' bug (I tested on Windows 10, Edge an Chrome).

Stopwatch not working, it's going way too faster

As I was looking for a simple Stopwatch implementation in JS, I found this code http://codepen.io/_Billy_Brown/pen/dbJeh/
The problem is that it's not working fine, the clock go way too fast. I got 30 seconds on the screen when i got only 23 seconds on my watch.
And I don't understand why. The timer function is called every millisecond and should be updating the time correctly.
setInterval(this.timer, 1);
Is the problem coming from the browser or from the JS code.
Thanks in advance.
The timers in Javascript doesn't have millisecond precision.
There is a minimum time for the interval, which differs depending on the browser and browser version. Typical minimums are 4 ms for recent browsers and 10 ms for a little older browsers.
Also, you can't rely on the callback being called at exact the time that you specify. Javascript is single threaded, which means that if some other code is running when the timer triggers a tick, it has to wait until that other code finishes.
In fact the code you gave is imitating time flow, but it is not synchronized with system time.
Every millisecond it just invokes the function this.time, which performs recounting of millis, seconds and so on
without getting native system time, but just adding 1 to variable representing "imaginary milliseconds".
So we can say that resulting pseudo-time you see depends on your CPU, browser and who knows what else.
On our modern fantastically fast computers the body of this.time function is being executed faster than millisecond (wondering what would happen on Pentium 2 with IE5 on board).
Anyhow there is no chance for the this.time to be executed exactly in particular fixed period on all computers and browsers.
The simplest correct way to show the time passed since startpoint according to the system time is:
<body>
<script>
var startTime = new Date() // assume this initialization to be start point
function getTimeSinceStart()
{
var millisSinceStart = new Date() - startTime
, millis = millisSinceStart % 1000
, seconds = Math.floor(millisSinceStart / 1000)
return [seconds, millis].join( ':' )
}
(function loop()
{
document.title = getTimeSinceStart() // look on the top of page
setTimeout( loop, 10 )
}())
</script>
</body>
P.S. What #Guffa says in his answer is correct (generally for js in browsers), but in this case it does not matter and not affect the problem

can setInterval drift over time?

I have 2 node.js webservers. I cache data inside webservers. I sync the cache load/clear based on system time. I have done time sync of all my hosts.
Now I clear cache every 15 mins using following code:
millisTillNexthour = "Calculate millis remaining until next hour"
setTimeout(function() {
setInterval(function() {
cache.clear();
}, 60000*15);
}, millisTillNexthour);
My expectation is even if this process runs for ever, cache will be cleared every 15th minute of each hour of the day.
My question is: can setInterval drift over time?
For eg: right now it clears cache at 10:00 10:15 10:30 10:45 11:00 ......
Can it happen that instead of 10:15 system time, setInterval gets executed at 10:20 system time when it was supposed to clear cache at 10:15??
I am not sure how this works. Please shed some light. I hope I explained my question well.
I'm probably more than a bit late to the party here, but this is how I solved this particular time-slipping problem just now, using a recursively called setTimeout() function instead of using setInterval().
var interval = 5000;
var adjustedInterval = interval;
var expectedCycleTime = 0;
function runAtInterval(){
// get timestamp at very start of function call
var now = Date.now();
// log with time to show interval
console.log(new Date().toISOString().replace(/T/, ' ').replace(/Z/, '') + " runAtInterval()");
// set next expectedCycleTime and adjustedInterval
if (expectedCycleTime == 0){
expectedCycleTime = now + interval;
}
else {
adjustedInterval = interval - (now - expectedCycleTime);
expectedCycleTime += interval;
}
// function calls itself after delay of adjustedInterval
setTimeout(function () {
runAtInterval();
}, adjustedInterval);
}
On each iteration, the function checks the actual execution time against the previously calculated expected time, and then deducts the difference from 'interval' to produce 'adjustedInterval'. This difference may be positive or negative, and the results show that actual execution times tend to oscillate around the 'true' value +/- ~5ms.
Either way, if you've got a task that is executing once a minute, and you run it for an entire day, using this function you can expect that - for the entire day - every single hour will have had 60 iterations happen. You won't have that occasional hour where you only got 59 results because eventually an entire minute had slipped.
setInterval is definitely drifting (although I agree that it should not be). I'm running a Node.js server with an interval of 30 seconds. On each tick, a few async web requests are made which from beginning to end take roughly 1 second. No other user-level/application processing happens in the intervening 29 seconds.
However, I notice from my server logs that over the course of 30 minutes, a drift of 100ms occurs. Of course, the underlying operating system is not to blame for the drift and it can only be some defect of Node.js's design or implementation.
I am very disappointed to notice that there is a bug in the NodeJS implementation of setInterval. Please take a look at here:
https://github.com/nodejs/node/issues/7346#issuecomment-300432730
You can use Date() object to set specific time and then add a certain number of milliseconds to the date.
It definitly can because of how Javascript works (See Event Loop)
Javascript event loop executes the setInterval queue when other queued events are finished. These events will take some time and it will effect your setInterval function's execute time and it will eventually drift away as time passes.
setInterval should not drift in a perfect world. It might be delayed due to other things taking up system resources. If you need a more precise solution to what you have, use the clock() function to " calibrate " your nodes.

JavaScript: Is this timer reliable?

Today I was introduced to the world of Web Workers in JavaScript. This made me rethink about timers. I used to program timers the ugly way, like this.
var time = -1;
function timerTick()
{
time++;
setTimeout("timerTick()",1000);
$("#timeI").html(time);
}
I know this could be improved by saving the date when you start the timer, but I've never been a fan of that.
Now I came up with a method using Web Workers, I did a little benchmark and found it much more reliable. Since I am not an expert on JavaScript I would like to know if this function works correct or what problems it might have thanks in advance.
My JavaScript code (please note I use JQuery):
$(function() {
//-- Timer using web worker.
var worker = new Worker('scripts/task.js'); //External script
worker.onmessage = function(event) { //Method called by external script
$("#timeR").html(event.data)
};
};
The external script ('scripts/task.js'):
var time = -1;
function timerTick()
{
time++;
setTimeout("timerTick()",1000);
postMessage(time);
}
timerTick();
You can also view a live demo on my website.
If you're trying to reliably display seconds ticking by, then the ONLY reliable way to do that is to get the current time at the start and use the timer ONLY for updating the screen. On each tick, you get the current time, compute the actual elapsed seconds and display that. Neither setTimeout() nor setInterval() are guaranteed or can be used for accurately counting time.
You can do it like this:
var start = +(new Date);
setInterval(function() {
var now = +(new Date);
document.getElementById("time").innerHTML = Math.round((now - start)/1000);
}, 1000);
If the browser gets busy and timers are erratically spaced, you may get a slightly irregular update on screen, but the elapsed time will remain accurate when the screen is updated. Your method is susceptible to accumulating error in the elapsed time.
You can see this work here: http://jsfiddle.net/jfriend00/Gfwze/
The most accurate timer would be a comparison of two time stamps. You could increase the precision of your timer by updating more frequently (such as every 100ms). I prefer using setInterval() over setTimeout().

Categories

Resources