Skip to content

Instantly share code, notes, and snippets.

@abstraktor
Created October 24, 2012 20:35
Show Gist options
  • Save abstraktor/3948703 to your computer and use it in GitHub Desktop.
Save abstraktor/3948703 to your computer and use it in GitHub Desktop.
Timer
define([
'underscore',
'backbone'
], function(_, Backbone){
/**
* static variables
**/
var nativeInterval = 10;
/**
* @constructor
* @param optional {Int} initial interval
* @example run the t1 to tick every second and t5 to tick every fifth second
* var t1 = new Timer(1000),
* t5 = new Timer(5000),
* logger = function(){console.log(arguments);};
* t1.bind('tick', logger);
* t5.bind('tick', logger);
* t1.start();t5.start();
**/
var Timer = function(interval){
//instance variables
this._timePassed = 0;
this._running = false;
this._interval = interval || 1000;
};
_.extend(Timer.prototype, Backbone.Events, {
/**
* starts the timer and triggers a 'tick' every __interval_ milliseconds
**/
start: function(){
if(this._running)
return;
this._running = true;
//kick off!
this.timerId = setInterval(_.bind(this._tick, this), nativeInterval);
this.trigger('start');
},
/**
* stops the timer immediately and resets the passed time
**/
stop: function(){
clearInterval(this.timerId);
this._timePassed = 0;
this._running = false;
this.trigger('stop');
},
/**
* @private
**/
_setTimePassed: function(newTimePassed){
this._timePassed = newTimePassed;
//raise events
if(this._timePassed >= this._interval){
this._timePassed -= this._interval;
this.trigger("tick", this._interval);
}
},
/**
* @private
* called every time, the native _interval timer ticks
**/
_tick: function(){
if(this._running)
this._setTimePassed(this._timePassed+nativeInterval);
},
// Getters and Setters
/**
* @brief sets the tick-_interval in milliseconds
* @param newInterval {Int} the new _interval
* if the timer is _running and the passed time exceeds the _interval, it will trigger *one* immediate tick and restart counting at 0
**/
setInterval: function(newInterval){
this._interval = newInterval;
if(this._timePassed > newInterval){
this._timePassed = 0;
this.trigger("tick", this._interval);
}
},
getInterval: function(){
return this._interval;
},
isRunning: function(){
return this._running;
},
/**
* @private
**/
_getTimePassed: function(){
return this._timePassed;
},
});
return Timer;
});
define([
'utils/timer'
], function(Timer) {
describe("Timer", function() {
var timer,
spy;
beforeEach(function(){
timer = new Timer;
spy = jasmine.createSpy();
timer.bind("tick", spy);
spy.reset();
});
it("#start to trigger 'tick'", function() {
timer.setInterval(500);
timer.start();
//not have been called
timer._setTimePassed(499);
expect(spy).not.toHaveBeenCalled();
//have been called once
timer._setTimePassed(500);
expect(spy).toHaveBeenCalled();
expect(spy).toHaveBeenCalledWith(500); // the same, as
// expect(spy.calls[0].args[0]).toEqual(500);
//have been called again
timer._setTimePassed(500);
expect(spy.calls.length).toEqual(2);
});
it("#setInterval to a lower value", function(){
timer.setInterval(1000);
timer.setInterval(500);
expect(spy).not.toHaveBeenCalled();
timer._setTimePassed(500);
expect(spy).toHaveBeenCalledWith(500);
expect(spy.calls.length).toEqual(1);
});
it("#setInterval while running", function(){
expect(spy.calls.length).toEqual(0);
timer.setInterval(1000);
timer.start();
timer._setTimePassed(599);
//raises 'tick' once and resets the timePassed to zero
timer.setInterval(200);
expect(spy).toHaveBeenCalledWith(200);
expect(spy.calls.length).toEqual(1);
expect(timer._getTimePassed()).toEqual(0);
});
it("#stop", function(){
timer.start();
timer.stop();
expect(spy).not.toHaveBeenCalled();
expect(spy.calls.length).toEqual(0);
});
it("times parallel", function(){
var t1 = new Timer(10),
t5 = new Timer(50),
spy1 = jasmine.createSpy('spy1'),
spy5 = jasmine.createSpy('spy5');
t1.bind('tick', spy1);
t5.bind('tick', spy5);
t1.start();
t5.start();
//expect none was called
runs(function(){
expect(spy1).not.toHaveBeenCalled();
expect(spy5).not.toHaveBeenCalled();
});
waits(13); //until it runs the following
//expect spy1 was called
runs(function(){
expect(spy1).toHaveBeenCalled();
expect(spy5).not.toHaveBeenCalled();
spy1.reset();
spy5.reset();
});
waits(43);
//expect spy5 was called and spy1 was called 4 times (additionally)
runs(function(){
expect(spy1.calls.length).toEqual(4);
expect(spy5.calls.length).toEqual(1);
spy1.reset();
spy5.reset();
});
runs(function(){
t5.stop();
});
waits(53);
runs(function(){
expect(spy1.calls.length).toEqual(5);
expect(spy5).not.toHaveBeenCalled();
});
});
});
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment