Skip to content

Instantly share code, notes, and snippets.

@marcinwyszynski
Last active December 24, 2015 16:09
Show Gist options
  • Save marcinwyszynski/6826466 to your computer and use it in GitHub Desktop.
Save marcinwyszynski/6826466 to your computer and use it in GitHub Desktop.
Timer for JavaScript.
function Metronome(interval, executions, func, context) {
if (interval < 1) {
throw "Interval must be a integer";
}
if (executions == 0) {
throw "Number of executions must be a positive integer";
}
// Initialize mutable private members.
var executionsLeft = executions;
var nextRun = null;
var timer = null;
var timeLeft = null;
// Run the closure asynchronously.
function run(once) {
nextRun = new Date().getTime() + interval;
setTimeout(function() {
func.call(context);
}, 0);
executionsLeft--;
if (once) return;
if (executionsLeft != 0) schedule();
}
// Schedule the closure.
function schedule() {
nextRun = new Date().getTime() + (timeLeft || interval);
timer = setTimeout(run, timeLeft || interval);
}
// Is the metronome currently running.
this.isRunning = function() {
return !!timer;
};
this.executionsLeft = function() {
if (executionsLeft < 0) return Infinity;
return executionsLeft;
};
// Time until next run, in miliseconds.
// Only meaningful if the metronome is currently running,
// otherwise it will just return null.
this.timeUntilNextRun = function() {
if (!this.isRunning()) return null;
return nextRun - new Date().getTime();
};
this.start = function() {
if (this.isRunning() || !executionsLeft) return false;
schedule();
return this.isRunning();
};
this.stop = function() {
if (!this.isRunning()) return false;
clearTimeout(timer);
timer = null;
return !this.isRunning();
};
this.pause = function() {
if (!this.isRunning()) return false;
timeLeft = this.timeUntilNextRun();
return this.stop();
};
this.resume = function() {
if (this.isRunning()) return false;
this.start();
timeLeft = null;
return this.isRunning();
};
// Runs the scheduled function _right now_. If the metronome was running,
// this resets the countdown.
this.runNow = function() {
run(!this.stop());
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment