function Timer(options) { options = options || {} this.onTick = options.onTick || function () {} this.onComplete = options.onComplete || function () {} this._duration = 0 this._remaining = 0 this._elapsed = 0 this._startTime = 0 this._pausedTime = 0 this._intervalId = null this._running = false this._paused = false this._completed = false } Timer.prototype.start = function (duration) { this._duration = duration this._remaining = duration this._elapsed = 0 this._completed = false this._running = true this._paused = false this._startTime = Date.now() this._tick() var self = this this._intervalId = setInterval(function () { self._tick() }, 1000) } Timer.prototype.pause = function () { if (!this._running || this._paused) return this._paused = true this._pausedTime = Date.now() clearInterval(this._intervalId) this._intervalId = null } Timer.prototype.resume = function () { if (!this._running || !this._paused) return this._startTime += Date.now() - this._pausedTime this._paused = false this._tick() var self = this this._intervalId = setInterval(function () { self._tick() }, 1000) } Timer.prototype.stop = function () { this._running = false this._paused = false clearInterval(this._intervalId) this._intervalId = null return this._elapsed } Timer.prototype._tick = function () { if (!this._running || this._paused) return this._elapsed = Math.floor((Date.now() - this._startTime) / 1000) this._remaining = Math.max(0, this._duration - this._elapsed) this.onTick({ remaining: this._remaining, elapsed: this._elapsed, duration: this._duration }) if (this._remaining <= 0 && !this._completed) { this._completed = true this.onComplete({ elapsed: this._elapsed, duration: this._duration }) } } Object.defineProperty(Timer.prototype, 'isRunning', { get: function () { return this._running && !this._paused } }) Object.defineProperty(Timer.prototype, 'isPaused', { get: function () { return this._paused } }) Object.defineProperty(Timer.prototype, 'isCompleted', { get: function () { return this._completed } }) Object.defineProperty(Timer.prototype, 'remaining', { get: function () { return this._remaining } }) Object.defineProperty(Timer.prototype, 'elapsed', { get: function () { return this._elapsed } }) module.exports = Timer