Skip to content

Instantly share code, notes, and snippets.

@leifoolsen
Last active August 29, 2015 14:17
Show Gist options
  • Save leifoolsen/22ce7681ad0f75eef1aa to your computer and use it in GitHub Desktop.
Save leifoolsen/22ce7681ad0f75eef1aa to your computer and use it in GitHub Desktop.
Timer with callback in JavaScript
// 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