Reputation: 11
I am implementing a countdown timer with Javascript setInterval and web worker. It is working fine in desktop but in the mobile browser the timer is slowing down when the browser is minimized (inactive mode).
Is there a way out to prevent the setInerval slow down issue in mobile?
Here is the glimpse of my code:
script.js
var hidden, visibilityChange;
if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support
hidden = "hidden";
visibilityChange = "visibilitychange";
} else if (typeof document.msHidden !== "undefined") {
hidden = "msHidden";
visibilityChange = "msvisibilitychange";
} else if (typeof document.webkitHidden !== "undefined") {
hidden = "webkitHidden";
visibilityChange = "webkitvisibilitychange";
}
document.addEventListener(visibilityChange, function (event) {
if( document[hidden] === false ){
// distance is a value of difference between current time and the end time
var days = Math.floor(distance / (60 * 60 * 24));
var hours = Math.floor((distance % (60 * 60 * 24)) / (60 * 60));
var minutes = Math.floor((distance % (60 * 60)) / 60);
var seconds = Math.floor(distance % 60);
var secondsLeft = (days * 24 * 3600) + (hours * 3600) + (minutes * 60) + seconds;
startTimer(distance, secondsLeft);
}
});
function startTimer(distance, secondsLeft)
{
// First check whether Web Workers are supported
if (typeof(Worker)!=="undefined"){
// Check whether Web Worker has been created. If not, create a new Web Worker based on the Javascript file simple-timer.js
if(w == null){
w = new Worker("../js/timer-worker.js");
w.postMessage({
'distance': distance,
'secondsLeft': secondsLeft
});
}
// Update timer div with output from Web Worker
w.onmessage = function (event) {
console.log(event.data.time_left_str);
};
} else {
// Web workers are not supported by your browser
console.log('Sorry, your browser does not support Web Workers ...');
}
}
timer-worker.js
var timerStart = true;
function myTimer(distance)
{
function pad(n) {
return (n < 10 ? "0" + n : n);
}
var hours = Math.floor((distance % (60 * 60 * 24)) / (60 * 60));
var minutes = Math.floor((distance % (60 * 60)) / 60);
var seconds = Math.floor(distance % (60));
var total_seconds = (hours * 60 * 60) + (minutes * 60) + seconds;
if( hours > 0 ){
time_left_str = pad(hours) + " hrs " + pad(minutes) + " mins " + pad(seconds) + " secs ";
}
else if( minutes > 0 ){
time_left_str = pad(minutes) + " mins " + pad(seconds) + " secs ";
}
else{
time_left_str = pad(seconds) + " secs ";
}
// return output to Web Worker
postMessage({
'time_left_str': time_left_str,
'total_seconds': total_seconds,
'distance_changed': distance
});
}
if (timerStart){
distance = null;
secondsLeft = null;
self.addEventListener('message', function(event) {
if(typeof(event.data.distance)!=="undefined"){
distance = event.data.distance;
}
if(typeof(event.data.secondsLeft)!=="undefined"){
secondsLeft = event.data.secondsLeft;
}
}, false);
// get current time
var d0=(new Date()).valueOf();
// repeat myTimer(d0) every 100 ms
myVar = setInterval(function(e){
//console.log('distance :: ' + distance);
myTimer(distance, secondsLeft);
distance--;
}, 1000);
// timer should not start anymore since it has been started
timerStart = false;
}
Upvotes: 0
Views: 1155
Reputation: 5353
Why would your countdown need to run every second even when the browser is not displayed ? I think this isn't your need, but to display an accurante countdown when the user is watching it.
Instead of decrementing your counter on every timer hoping it would execute precisely every seconds, you should just recompute the distance from the moment the page first loaded, preventing any hazard effect to occur :
//happens on the loading of the page
var d0 = new Date();
var initDistance = //compute initial distance here
var distance = initDistance;
// ... in the refresh function
var distance = //recompute distance based on initDistance and the difference between new Date() and d0
// do the same for secondLeft if needed.
Upvotes: 1