bitmovin-player-ui
Version:
Bitmovin Player UI Framework
110 lines (96 loc) • 3.11 kB
text/typescript
// TODO change to internal (not exported) class, how to use in other files?
/**
* Executes a callback after a specified amount of time, optionally repeatedly until stopped.
*/
export class Timeout {
private readonly delay: number;
private readonly callback: () => void;
private readonly repeat: boolean;
// There's two setTimeout declarations, one on Window which returns type "number" and one in NodeJS which returns
// type "Timer". For unknown reasons builds on Jenkins fail due to a type mismatch when we use type "number" here,
// although it works on other platforms (e.g. Windows, Codeship).
// To work around the issue we use type "any". The type does not matter anyway because we're not working with
// this value except providing it to clearTimeout.
private timeoutOrIntervalId: any;
private active: boolean;
private suspended: boolean;
/**
* Creates a new timeout callback handler.
* @param delay the delay in milliseconds after which the callback should be executed
* @param callback the callback to execute after the delay time
* @param repeat if true, call the callback repeatedly in delay intervals
*/
constructor(delay: number, callback: () => void, repeat: boolean = false) {
this.delay = delay;
this.callback = callback;
this.repeat = repeat;
this.timeoutOrIntervalId = 0;
this.active = false;
this.suspended = false;
}
/**
* Starts the timeout and calls the callback when the timeout delay has passed. Has no effect when the timeout is
* suspended.
* @returns {Timeout} the current timeout (so the start call can be chained to the constructor)
*/
start(): this {
this.reset();
return this;
}
/**
* Clears the timeout. The callback will not be called if clear is called during the timeout.
*/
clear(): void {
this.clearInternal();
}
/**
* Suspends the timeout. The callback will not be called and calls to `start` and `reset` will be ignored until the
* timeout is resumed.
*/
suspend() {
this.suspended = true;
this.clearInternal();
return this;
}
/**
* Resumes the timeout.
* @param reset whether to reset the timeout after resuming
*/
resume(reset: boolean) {
this.suspended = false;
if (reset) {
this.reset();
}
return this;
}
/**
* Resets the passed timeout delay to zero. Can be used to defer the calling of the callback. Has no effect if the
* timeout is suspended.
*/
reset(): void {
this.clearInternal();
if (this.suspended) {
return;
}
if (this.repeat) {
this.timeoutOrIntervalId = setInterval(this.callback, this.delay);
} else {
this.timeoutOrIntervalId = setTimeout(() => {
this.active = false;
this.callback();
}, this.delay);
}
this.active = true;
}
isActive(): boolean {
return this.active;
}
private clearInternal(): void {
if (this.repeat) {
clearInterval(this.timeoutOrIntervalId);
} else {
clearTimeout(this.timeoutOrIntervalId);
}
this.active = false;
}
}