retimer
Version:
Reschedulable Timer for your node needs
83 lines (67 loc) • 1.83 kB
JavaScript
'use strict'
const getTime = require('./time')
const { clearTimeout, setTimeout } = require('./timers')
class Retimer {
constructor (callback, timeout, args) {
const that = this
this._started = getTime()
this._rescheduled = 0
this._scheduled = timeout
this._args = args
this._triggered = false
this._timerWrapper = () => {
if (that._rescheduled > 0) {
that._scheduled = that._rescheduled - (getTime() - that._started)
that._schedule(that._scheduled)
} else {
that._triggered = true
callback.apply(null, that._args)
}
}
this._timer = setTimeout(this._timerWrapper, timeout)
}
reschedule (timeout) {
if (!timeout) {
timeout = this._scheduled
}
const now = getTime()
if ((now + timeout) - (this._started + this._scheduled) < 0) {
clearTimeout(this._timer)
this._schedule(timeout)
} else if (!this._triggered) {
this._started = now
this._rescheduled = timeout
} else {
this._schedule(timeout)
}
}
_schedule (timeout) {
this._triggered = false
this._started = getTime()
this._rescheduled = 0
this._scheduled = timeout
this._timer = setTimeout(this._timerWrapper, timeout)
}
clear () {
clearTimeout(this._timer)
}
}
function retimer () {
if (typeof arguments[0] !== 'function') {
throw new Error('callback needed')
}
if (typeof arguments[1] !== 'number') {
throw new Error('timeout needed')
}
let args
if (arguments.length > 0) {
args = new Array(arguments.length - 2)
/* eslint-disable no-var */
for (var i = 0; i < args.length; i++) {
args[i] = arguments[i + 2]
}
}
return new Retimer(arguments[0], arguments[1], args)
}
module.exports = retimer
module.exports.Retimer = Retimer