mtcute/packages/core/src/utils/early-timer.ts

85 lines
1.9 KiB
TypeScript
Raw Normal View History

/**
* 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 = () => {}
constructor() {
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.reset()
this._handler()
}
/**
* 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
}
}