Skip to content

Instantly share code, notes, and snippets.

@RodrigoNovais
Last active May 19, 2021 03:14
Show Gist options
  • Save RodrigoNovais/480dca42b3ed19ac788209196554a581 to your computer and use it in GitHub Desktop.
Save RodrigoNovais/480dca42b3ed19ac788209196554a581 to your computer and use it in GitHub Desktop.
Utility timer class
import EventEmitter from 'events';
export interface TimerEvents {
'tick': (time: number) => void;
'complete': () => void;
}
export interface Timer {
addListener<U extends keyof TimerEvents>(event: U, listener: TimerEvents[U]): this;
prependListener<U extends keyof TimerEvents>(event: U, listener: TimerEvents[U]): this;
prependOnceListener<U extends keyof TimerEvents>(event: U, listener: TimerEvents[U]): this;
removeListener<U extends keyof TimerEvents>(event: U, listener: TimerEvents[U]): this;
removeAllListeners(event?: keyof TimerEvents): this;
once<U extends keyof TimerEvents>(event: U, listener: TimerEvents[U]): this;
on<U extends keyof TimerEvents>(event: U, listener: TimerEvents[U]): this;
off<U extends keyof TimerEvents>(event: U, listener: TimerEvents[U]): this;
emit<U extends keyof TimerEvents>(event: U, ...args: Parameters<TimerEvents[U]>): boolean;
eventNames<U extends keyof TimerEvents>(): U[];
listenerCount(type: keyof TimerEvents): number;
listeners<U extends keyof TimerEvents>(type: U): TimerEvents[U][];
rawListeners<U extends keyof TimerEvents>(type: U): TimerEvents[U][];
}
const A_SECOND_IN_MILLISECONDS = 1000;
const A_MINUTE_IN_SECONDS = 60;
export class Timer extends EventEmitter {
private start: number;
private _running: boolean;
public get running(): boolean { return this._running; }
private remaining: number = A_SECOND_IN_MILLISECONDS;
private delay: number = A_SECOND_IN_MILLISECONDS;
private time: number = A_MINUTE_IN_SECONDS;
private currentTime: number = A_MINUTE_IN_SECONDS;
private timerId: NodeJS.Timeout;
public constructor() { super(); }
public setTime(timeInSeconds: number): void {
this.time = timeInSeconds;
this.currentTime = timeInSeconds;
this.pause();
this.reset();
}
public getTime(): number { return this.currentTime; }
public setPace(timeInMilliseconds: number): void {
this.remaining = timeInMilliseconds;
this.delay = timeInMilliseconds;
this.pause();
this.reset();
}
public getPace(): number { return this.delay; }
public pause(): void {
clearTimeout(this.timerId);
this.remaining -= Date.now() - this.start;
this._running = false;
}
public resume(): void {
this._running = true;
this.start = Date.now();
this.timerId = setTimeout(() => {
this.remaining = this.delay;
this.currentTime = this.currentTime - 1;
this.emit('tick', this.currentTime);
this.loop();
}, this.remaining);
}
public reset(): void {
this.remaining = this.delay;
this.currentTime = this.time;
this._running = false;
}
private loop(): void {
if (this.currentTime)
return this.resume();
this._running = false;
this.emit('complete');
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment