timers.js 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. 'use strict'
  2. let fastNow = Date.now()
  3. let fastNowTimeout
  4. const fastTimers = []
  5. function onTimeout () {
  6. fastNow = Date.now()
  7. let len = fastTimers.length
  8. let idx = 0
  9. while (idx < len) {
  10. const timer = fastTimers[idx]
  11. if (timer.state === 0) {
  12. timer.state = fastNow + timer.delay
  13. } else if (timer.state > 0 && fastNow >= timer.state) {
  14. timer.state = -1
  15. timer.callback(timer.opaque)
  16. }
  17. if (timer.state === -1) {
  18. timer.state = -2
  19. if (idx !== len - 1) {
  20. fastTimers[idx] = fastTimers.pop()
  21. } else {
  22. fastTimers.pop()
  23. }
  24. len -= 1
  25. } else {
  26. idx += 1
  27. }
  28. }
  29. if (fastTimers.length > 0) {
  30. refreshTimeout()
  31. }
  32. }
  33. function refreshTimeout () {
  34. if (fastNowTimeout && fastNowTimeout.refresh) {
  35. fastNowTimeout.refresh()
  36. } else {
  37. clearTimeout(fastNowTimeout)
  38. fastNowTimeout = setTimeout(onTimeout, 1e3)
  39. if (fastNowTimeout.unref) {
  40. fastNowTimeout.unref()
  41. }
  42. }
  43. }
  44. class Timeout {
  45. constructor (callback, delay, opaque) {
  46. this.callback = callback
  47. this.delay = delay
  48. this.opaque = opaque
  49. // -2 not in timer list
  50. // -1 in timer list but inactive
  51. // 0 in timer list waiting for time
  52. // > 0 in timer list waiting for time to expire
  53. this.state = -2
  54. this.refresh()
  55. }
  56. refresh () {
  57. if (this.state === -2) {
  58. fastTimers.push(this)
  59. if (!fastNowTimeout || fastTimers.length === 1) {
  60. refreshTimeout()
  61. }
  62. }
  63. this.state = 0
  64. }
  65. clear () {
  66. this.state = -1
  67. }
  68. }
  69. module.exports = {
  70. setTimeout (callback, delay, opaque) {
  71. return delay < 1e3
  72. ? setTimeout(callback, delay, opaque)
  73. : new Timeout(callback, delay, opaque)
  74. },
  75. clearTimeout (timeout) {
  76. if (timeout instanceof Timeout) {
  77. timeout.clear()
  78. } else {
  79. clearTimeout(timeout)
  80. }
  81. }
  82. }