retimer.js 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. 'use strict'
  2. const getTime = require('./time')
  3. const { clearTimeout, setTimeout } = require('./timers')
  4. class Retimer {
  5. constructor (callback, timeout, args) {
  6. const that = this
  7. this._started = getTime()
  8. this._rescheduled = 0
  9. this._scheduled = timeout
  10. this._args = args
  11. this._triggered = false
  12. this._timerWrapper = () => {
  13. if (that._rescheduled > 0) {
  14. that._scheduled = that._rescheduled - (getTime() - that._started)
  15. that._schedule(that._scheduled)
  16. } else {
  17. that._triggered = true
  18. callback.apply(null, that._args)
  19. }
  20. }
  21. this._timer = setTimeout(this._timerWrapper, timeout)
  22. }
  23. reschedule (timeout) {
  24. if (!timeout) {
  25. timeout = this._scheduled
  26. }
  27. const now = getTime()
  28. if ((now + timeout) - (this._started + this._scheduled) < 0) {
  29. clearTimeout(this._timer)
  30. this._schedule(timeout)
  31. } else if (!this._triggered) {
  32. this._started = now
  33. this._rescheduled = timeout
  34. } else {
  35. this._schedule(timeout)
  36. }
  37. }
  38. _schedule (timeout) {
  39. this._triggered = false
  40. this._started = getTime()
  41. this._rescheduled = 0
  42. this._scheduled = timeout
  43. this._timer = setTimeout(this._timerWrapper, timeout)
  44. }
  45. clear () {
  46. clearTimeout(this._timer)
  47. }
  48. }
  49. function retimer () {
  50. if (typeof arguments[0] !== 'function') {
  51. throw new Error('callback needed')
  52. }
  53. if (typeof arguments[1] !== 'number') {
  54. throw new Error('timeout needed')
  55. }
  56. let args
  57. if (arguments.length > 0) {
  58. args = new Array(arguments.length - 2)
  59. /* eslint-disable no-var */
  60. for (var i = 0; i < args.length; i++) {
  61. args[i] = arguments[i + 2]
  62. }
  63. }
  64. return new Retimer(arguments[0], arguments[1], args)
  65. }
  66. module.exports = retimer
  67. module.exports.Retimer = Retimer