Last active
August 29, 2015 14:17
-
-
Save leifoolsen/22ce7681ad0f75eef1aa to your computer and use it in GitHub Desktop.
Timer with callback in JavaScript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// See e.g: http://www.sitepoint.com/creating-accurate-timers-in-javascript/ | |
// http://stackoverflow.com/questions/3969475/javascript-pause-settimeout | |
Timer = function(duration, resolution, delegates) { | |
'use strict'; | |
duration || (duration = 1000); | |
resolution || (resolution = 20); | |
delegates || (delegates = {}); | |
delegates.onStart || (delegates.onStart = function(){} ); | |
delegates.onProgress || (delegates.onProgress = function(){} ); | |
delegates.onStop || (delegates.onStop = function(){} ); | |
var steps = Math.max(1, (duration / 100) * (resolution / 10)), | |
speed = duration / steps, | |
count, | |
start, | |
timeoutId; | |
this.run = function() { | |
killTimer() | |
count = 0; | |
start = new Date().getTime(); | |
delegates.onStart(steps, count); | |
doTimer(); | |
}; | |
this.resume = function() { | |
start = new Date().getTime(); | |
doTimer(); | |
}; | |
this.disconnect = function() { | |
killTimer() | |
}; | |
function killTimer() { | |
if(timeoutId) { | |
window.clearTimeout(timeoutId); | |
timeoutId = undefined; | |
} | |
}; | |
function doTimer() { | |
if(++count == steps) { | |
delegates.onStop(steps, count); | |
} | |
else { | |
var pause = delegates.onProgress(steps, count); | |
if(!pause) { | |
var diff = (new Date().getTime() - start); | |
if(diff > duration) { | |
delegates.onStop(steps, count); | |
} | |
else { | |
diff -= (count * speed); | |
timeoutId = window.setTimeout(doTimer, (speed - diff)); | |
} | |
} | |
} | |
}; | |
return this; | |
}; | |
// Run the timer and compare to timer without adjustment | |
(function(){ | |
var d, | |
n, | |
stepTimeout = function() { | |
console.log("\n* StepTimeout start"); | |
n = 0; | |
d = new Date(); | |
var j = 0; | |
function doSillyWork() { | |
// Do some silly work | |
for (var c = 0; c < Math.floor((Math.random() * 1000000) + 100000); c++) { | |
n++ | |
} | |
if(!(j % 6)) { | |
console.log(" StepTimeout progress. steps:" + j); | |
} | |
if(++j == 50) { | |
// Should have duration >>> Timer duration | |
console.log("* StepTimeout finished @ " + (new Date() - d) + "ms. n: " + n); | |
} | |
else { | |
window.setTimeout(doSillyWork, 40); | |
} | |
}; | |
window.setTimeout(doSillyWork, 40); | |
}, | |
oneTimeout = function() { | |
console.log("\n* Single timeout start"); | |
d = new Date(); | |
window.setTimeout(function() { | |
// No workload. Should have duration ~ Timer duration | |
console.log("* Single timeout finished @ " + (new Date() - d) + "ms"); | |
stepTimeout(); | |
}, 2000); | |
}; | |
new Timer(2000, 30, { | |
onStart: function(steps, count) { | |
n = 0; | |
d = new Date(); | |
console.log("* Timer start"); | |
console.log(" Timer progress. steps:" + steps + ", count: " + count); | |
}, | |
onProgress: function(steps, count) { | |
if(!(count % 6)) { | |
console.log(" Timer progress. steps:" + steps + ", count: " + count); | |
} | |
// Do some silly work | |
for (var i = 0; i < Math.floor((Math.random() * 1000000) + 100000); i++) { | |
n++ | |
} | |
}, | |
onStop: function(steps, count) { | |
console.log(" Timer progress. steps:" + steps + ", count: " + count); | |
if(count < steps) { | |
console.log(" * Timer finished before work was done!"); | |
} | |
console.log("* Timer finished @ " + (new Date() - d) + "ms. n: " + n); | |
oneTimeout(); | |
} | |
}).run(); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment