smarttime/ts/smarttime.classes.timer.ts
2023-10-20 12:50:47 +02:00

87 lines
2.0 KiB
TypeScript

import * as plugins from './smarttime.plugins.js';
import { TimeStamp } from './smarttime.classes.timestamp.js';
export type TimerState = 'initiated' | 'started' | 'paused' | 'completed';
export class Timer {
/**
* the original amount of milliseconds for this Timer
*/
public timeInMilliseconds: number;
/**
* the state of the timer
*/
public state: TimerState = 'initiated';
/**
* completed Promise
*/
public completed: Promise<void>;
/**
* a reference to when the Timeout started
*/
public startedAt: TimeStamp;
/**
* a reference to when a Timer has been potentially paused
*/
public pausedAt: TimeStamp;
get timeLeft(): number {
return this.timeInMilliseconds - this.pausedAt.change;
}
/**
* the current timeout the needs to be canceled when this Timer is stopped
*/
private currentTimeout: NodeJS.Timeout;
// a deferred triggeted when Timer has completed
private completedDeferred = plugins.smartpromise.defer<void>();
constructor(timeInMillisecondsArg: number) {
this.timeInMilliseconds = timeInMillisecondsArg;
this.completed = this.completedDeferred.promise;
}
/**
* starts the timer
*/
public start() {
if (!this.startedAt) {
this.currentTimeout = setTimeout(() => {
this.completedDeferred.resolve();
}, this.timeInMilliseconds);
this.startedAt = new TimeStamp();
} else {
throw new Error('timer has been started before. Please use resume instead');
}
}
public pause() {
if (this.startedAt) {
clearTimeout(this.currentTimeout);
this.currentTimeout = null;
this.pausedAt = TimeStamp.fromTimeStamp(this.startedAt);
}
}
public resume() {
if (this.startedAt) {
this.currentTimeout = setTimeout(() => {
this.completedDeferred.resolve();
}, this.timeLeft);
} else {
throw new Error('timer has NOT been started before. Please use .start() instead');
}
}
public reset() {
this.pause();
this.startedAt = null;
this.pausedAt = null;
}
}