2021-11-23 00:03:59 +03:00
|
|
|
/**
|
|
|
|
* Wrapper over JS timers that allows re-scheduling them
|
|
|
|
* to earlier time
|
|
|
|
*/
|
|
|
|
export class EarlyTimer {
|
|
|
|
private _timeout?: NodeJS.Timeout
|
|
|
|
private _immediate?: NodeJS.Immediate
|
|
|
|
private _timeoutTs?: number
|
|
|
|
|
|
|
|
private _handler: () => void = () => {}
|
|
|
|
|
2022-06-30 16:32:56 +03:00
|
|
|
constructor() {
|
2021-11-23 00:03:59 +03:00
|
|
|
this.emitNow = this.emitNow.bind(this)
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Emit the timer when the event loop is idle
|
|
|
|
* (basically `setImmediate()`)
|
|
|
|
*/
|
|
|
|
emitWhenIdle(): void {
|
|
|
|
if (this._immediate) return
|
|
|
|
|
|
|
|
clearTimeout(this._timeout!)
|
|
|
|
this._timeoutTs = Date.now()
|
|
|
|
|
|
|
|
if (typeof setImmediate !== 'undefined') {
|
|
|
|
this._immediate = setImmediate(this.emitNow)
|
|
|
|
} else {
|
|
|
|
this._timeout = setTimeout(this.emitNow, 0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Emit the timer before the next given milliseconds
|
|
|
|
*
|
|
|
|
* Shorthand for `emitBefore(Date.now() + ms)`
|
|
|
|
*
|
|
|
|
* @param ms Milliseconds to schedule for
|
|
|
|
*/
|
|
|
|
emitBeforeNext(ms: number): void {
|
|
|
|
return this.emitBefore(Date.now() + ms)
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Emit the timer before the given time
|
|
|
|
*
|
|
|
|
* @param ts Unix time in MS
|
|
|
|
*/
|
|
|
|
emitBefore(ts: number): void {
|
|
|
|
if (!this._timeoutTs || ts < this._timeoutTs) {
|
|
|
|
this.reset()
|
|
|
|
this._timeout = setTimeout(this.emitNow, ts - Date.now())
|
|
|
|
this._timeoutTs = ts
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Emit the timer right now
|
|
|
|
*/
|
|
|
|
emitNow(): void {
|
|
|
|
this._handler()
|
|
|
|
this.reset()
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Cancel the timer
|
|
|
|
*/
|
|
|
|
reset(): void {
|
|
|
|
if (this._immediate) {
|
|
|
|
clearImmediate(this._immediate!)
|
|
|
|
this._immediate = undefined
|
|
|
|
} else {
|
|
|
|
clearTimeout(this._timeout!)
|
|
|
|
}
|
|
|
|
this._timeoutTs = undefined
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set timeout handler
|
|
|
|
*/
|
|
|
|
onTimeout(handler: () => void): void {
|
|
|
|
this._handler = handler
|
|
|
|
}
|
|
|
|
}
|