Skip to content

Instantly share code, notes, and snippets.

@burdiuz
Last active March 27, 2017 07:02
Show Gist options
  • Save burdiuz/835f7e85ea427c3f0ff157a2f0026176 to your computer and use it in GitHub Desktop.
Save burdiuz/835f7e85ea427c3f0ff157a2f0026176 to your computer and use it in GitHub Desktop.
{
"name": "Timer",
"description": "Implementation of AS3 Timer",
"version": "0.0.1",
"main": "Timer.js",
"dependencies": {
"SymbolImpl": "https://gist.github.com/burdiuz/7664491eed84695250e46be20670be84",
"event-dispatcher": "git://github.com/burdiuz/js-event-dispatcher.git"
}
}
'use strict';
import SymbolImpl from 'SymbolImpl';
import EventDispatcher from 'event-dispatcher';
const INTERNALS_FIELD = SymbolImpl('timer::internals');
const getInitObject = (delay, repeatCount,) => ({
delay,
repeatCount,
currentCount: 0,
intervalId: 0,
});
export class TimerEvent {
static TIMER = 'timer';
static TIMER_COMPLETE = 'timerComplete';
type;
currentCount;
constructor(type, currentCount = 0) {
this.type = type;
this.currentCount = currentCount;
}
}
/**
* Implementation of AS3 Timer.
* http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/utils/Timer.html
* @event timer Dispatched whenever a Timer object reaches an interval specified according to the Timer.delay property.
* @event timerComplete Dispatched whenever it has completed the number of requests set by Timer.repeatCount.
*/
class Timer extends EventDispatcher {
/**
* Constructs a new Timer object with the specified delay and repeatCount states.
* The timer does not start automatically; you must call the start() method to start it.
* @param delay
* @param repeatCount
*/
constructor(delay, repeatCount = 0) {
super();
this[INTERNALS_FIELD] = getInitObject(delay, repeatCount);
}
/**
* [read-only] The total number of times the timer has fired since it started at zero.
* If the timer has been reset, only the fires since the reset are counted.
* @returns {number}
*/
get currentCount() {
return this[INTERNALS_FIELD].currentCount;
}
/**
* [read-only] The timer's current state; true if the timer is running, otherwise false.
* @returns {boolean}
*/
get running() {
return Boolean(this[INTERNALS_FIELD].intervalId);
}
/**
* The delay, in milliseconds, between timer events. If you set the delay interval while
* the timer is running, the timer will restart at the same repeatCount iteration.
* @returns {number}
*/
get delay() {
return this[INTERNALS_FIELD].delay;
}
set delay(value: number) {
const { delay, intervalId } = this[INTERNALS_FIELD];
if (delay !== value) {
this[INTERNALS_FIELD].delay = value;
if (intervalId) {
this.reset();
this.start();
}
}
}
/**
* The total number of times the timer is set to run. If the repeat count is set to 0,
* the timer continues indefinitely, or until the stop() method is invoked or the program stops.
* If the repeat count is nonzero, the timer runs the specified number of times. If repeatCount
* is set to a total that is the same or less then currentCount the timer stops and will not fire again.
* @returns {number}
*/
get repeatCount() {
return this[INTERNALS_FIELD].repeatCount;
}
set repeatCount(value: number) {
const { currentCount } = this[INTERNALS_FIELD];
this[INTERNALS_FIELD].repeatCount = value;
if (value >= currentCount) {
this.stop();
}
}
/**
* Stops the timer, if it is running, and sets the currentCount property back to 0,
* like the reset button of a stopwatch. Then, when start() is called, the timer instance
* runs for the specified number of repetitions, as set by the repeatCount value.
*/
reset() {
const { intervalId, delay, repeatCount, } = this[INTERNALS_FIELD];
clearInterval(intervalId);
this[INTERNALS_FIELD] = getInitObject(delay, repeatCount);
}
/**
* Starts the timer, if it is not already running.
*/
start() {
this[INTERNALS_FIELD].intervalId = setInterval(() => {
let { currentCount, repeatCount, } = this[INTERNALS_FIELD];
this[INTERNALS_FIELD].currentCount = ++currentCount;
if (this.hasEventListener(TimerEvent.TIMER)) {
this.dispatchEvent(new TimerEvent(TimerEvent.TIMER, currentCount));
}
if (repeatCount && currentCount >= repeatCount && this.hasEventListener(TimerEvent.TIMER_COMPLETE)) {
this.dispatchEvent(new TimerEvent(TimerEvent.TIMER, currentCount));
this.stop();
}
}, this[INTERNALS_FIELD].delay);
}
/**
* Stops the timer. When start() is called after stop(), the timer instance runs
* for the remaining number of repetitions, as set by the repeatCount property.
*/
stop() {
clearInterval(this[INTERNALS_FIELD].intervalId);
this[INTERNALS_FIELD].intervalId = 0;
}
}
Timer.TimerEvent = TimerEvent;
export default Timer;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment