Skip to content

Instantly share code, notes, and snippets.

@EvAlex
Last active April 20, 2017 00:26
Show Gist options
  • Save EvAlex/f9de5838a87f9a9e9ebc4e2425a761b7 to your computer and use it in GitHub Desktop.
Save EvAlex/f9de5838a87f9a9e9ebc4e2425a761b7 to your computer and use it in GitHub Desktop.
TypeScript Timer based on requestAnimationFrame()
class Timer {
private _tasks: ITimerTask[] = [];
private _enabled = false;
register(fn: Function, period: number, dueTime = 0): number {
const id = this._tasks.map(t => t.id).reduce((p, c) => p > c ? p : c, 0) + 1;
this._tasks.push({
id: id,
registerTime: new Date(),
lastRunTime: null,
dueTime: dueTime,
period: period,
fn: fn
});
if (this._tasks.length === 1) {
this.start();
}
return id;
}
unregister(id: number) {
const match = this._tasks.filter(t => t.id === id)[0];
if (match) {
const i = this._tasks.indexOf(match);
this._tasks.splice(i, 1);
if (this._tasks.length === 0) {
this.stop();
}
}
}
private start() {
this._enabled = true;
const handler = () => {
this.runRegisteredTasks(new Date());
if (this._enabled) {
window.requestAnimationFrame(handler);
}
};
window.requestAnimationFrame(handler);
}
private stop() {
this._enabled = false;
}
private runRegisteredTasks(time: Date) {
const toRun = this.getTasksToRun(time);
this.runTasks(toRun);
}
private getTasksToRun(time: Date): ITimerTask[] {
const toRun: ITimerTask[] = [];
for (const task of this._tasks) {
if (task.lastRunTime === null && time.getTime() > task.registerTime.getTime() + task.dueTime) {
toRun.push(task);
} else {
const lastRunTimeLatency = (task.lastRunTime.getTime() - (task.registerTime.getTime() + task.dueTime)) % task.period;
const lastIntendedRunTime = task.lastRunTime.getTime() - lastRunTimeLatency;
const nextRunTime = lastIntendedRunTime + task.period;
if (time.getTime() > nextRunTime) {
toRun.push(task);
}
}
}
return toRun;
}
private runTasks(tasks: ITimerTask[]) {
for (const task of tasks) {
task.fn();
}
}
}
export const timer = new Timer();
interface ITimerTask {
id: number;
registerTime: Date;
lastRunTime: Date;
dueTime: number;
period: number;
fn: Function;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment