JavaScript setTimeout and changes to system time cause problems
Use setInterval
instead of setTimeout
and your problems should be resolved :)
Update:
If you really cannot use either setTimeout or setInterval, you could try to have a hidden iframe
that loads a simple HTML page that looks something like this:
<html>
<head>
<meta http-equiv="refresh" content="300"/>
<script>
document.domain='same as parent page';
top.ajax_function_you_wish_to_trigger();
</script>
</head>
<body>
</body>
</html>
If you are lucky the meta refresh won't cause you the same problems.
Another solution would be to move the event firing to the server via server push. There are many reasons not to do this, not the least that you'd centralize the events and make them a burden on the server, but it could be considered a last resort.
What I will do is change from opening a new Ajax request every 5 seconds to using Comet (long polling). It is a better option because the server will push the new results to the browser every time that they are needed, this can be every 5 seconds on server side or every time new information is available.
Even better would be to use web sockets and have Comet as fall back. This is easy to implement with Faye or socket.io.
There are other options, like CometD or Ape.
I recently encountered this problem too. In my case time change might cause serious financial loses so I had to take it seriously.
Some background:
- IE and Opera handles systems time change properly (no side effects to
setTimeout()
,setInterval()
). - FF < 4.0 and all Webkit based browser fails to handle changing time to the past (exactly as you described). Note: timers in Chrome however stops only after some time ~2-60s.
My solution: use some event from user interaction (i.e. mousemove
, mouseover
, etc) to trigger time change check.
Clock.prototype.checkLocalTime = function(){
var diff = Date.now()- this.lastTimestamp;
if ( diff < 0 || diff > 20000) { // if time shifted back or more than 20s to the future
console.warn('System time changed! By ' + diff + 'ms' );
this.restartTimer();
this.getServerTime();
}
this.lastTimestamp = time;
}
As you can notice I restart timer and additionally synchronize time with server.