brentburgoyne/timer-machine

View on GitHub
lib/timer.js

Summary

Maintainability
A
0 mins
Test Coverage
/**
 * Module dependencies.
 */
var EventEmitter = require('events').EventEmitter
var inherits     = require('util').inherits

/**
 * Expose `Timer`.
 */
module.exports = Timer

/**
 * Stores named timers.
 */
var timers = {}

/**
 * Initialize a `Timer` object
 * @param {Boolean} start
 * @api public
 */
function Timer(start) {
  EventEmitter.call(this)
  this._total = 0
  this._start = null
  this._startCount = 0
  if (start) {
    this.start()
  }
}

/**
 * Timer extends EventEmitter.
 */
inherits(Timer, EventEmitter)

/**
 * Get a named timer, initialize a new one if it does not exist.
 * @param {String} name
 * @return {Timer}
 * @api public
 */
Timer.get = function (name) {
  if (!timers[name]) {
    timers[name] = new Timer()
  }
  return timers[name]
}

/**
 * Destroy an existing named timer.
 * @param {String} name
 * @return {Boolean}
 * @api public
 */
Timer.destroy = function (name) {
  if (timers[name]) {
    return delete timers[name]
  }
  return false
}

/**
 * Get the total milliseconds the timer has run.
 * @return {Number}
 * #api public
 */
Timer.prototype.time = function () {
  var total = this._total
  total += this.timeFromStart()
  return total
}

/**
 * Get the total millisseonds the time has run and emit time event.
 * @return {Number}
 */
Timer.prototype.emitTime = function () {
  var time = this.time()
  this.emit('time', time)
  return time
}

/**
 * Get the time in milliseconds since the timer was last started.
 * @return {Number}
 * @api public
 */
Timer.prototype.timeFromStart = function () {
  return this.isStarted() ? now() - this._start : 0
}

/**
 * Check to see if the timer object is currently started.
 * @return {Boolean}
 * @api public
 */
Timer.prototype.isStarted = function () {
  return !this.isStopped()
}

/**
 * Check to see if the timer object is currently stopped.
 * @return {Boolean}
 * @api public
 */
Timer.prototype.isStopped = function () {
  return this._start === null
}

/**
 * Start the timer if it was not already started.
 * @return {Boolean}
 * @api public
 */
Timer.prototype.start = function () {
  ++this._startCount
  if (this.isStopped()) {
    this._start = now()
    this.emit('start')
    return true
  }
  return false
}

/**
 * Stop the timer if it was not already stopped.
 * @return {Boolean}
 * @api public
 */
Timer.prototype.stop = function () {
  if (this.isStarted()) {
    this._total += this.timeFromStart()
    this._start = null
    this._stopCount = 0
    this.emit('stop')
    return true
  }
  return false
}

/**
 * Stop the timer if once called equal to the number of times start was called.
 * @return {Boolean} true if timer was stopped
 * @api public
 */
Timer.prototype.stopParallel = function () {
  if (this.isStarted()) {
    --this._startCount
    if (this._startCount === 0) {
      return this.stop()
    }
  }
  return false
}

/**
 * Start or stop the timer depending on current state.
 * @return {Boolean}
 * @api public
 */
Timer.prototype.toggle = function () {
  return this.start() || this.stop()
}

/**
 * Return a string representation of the timer.
 * @return {String}
 */
Timer.prototype.toString = function () {
  return this.time() + 'ms'
}

/**
 * Return a numeric value of the timer in milliseconds.
 * @return {Number}
 */
Timer.prototype.valueOf = function () {
  return this.time()
}

/**
 * Get the current time in milliseconds.
 * @return {Number}
 * @api private
 */
function now() {
  return new Date().getTime();
}