index.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. // All common browsers limit the interval to 2^31 numbers.
  2. // For this reason, we need some workarounds if we want to use intervals larger than that.
  3. exports.maxInterval = Math.pow(2, 31) - 1;
  4. function clamp(interval) {
  5. return interval <= exports.maxInterval ? interval : exports.maxInterval;
  6. }
  7. function Timeout(cb, args, thisArg) {
  8. this.timestamp = null;
  9. this.timer = null;
  10. this.cb = cb;
  11. this.args = args;
  12. this.thisArg = thisArg;
  13. }
  14. Timeout.fired = function (timeout) {
  15. var now = Date.now();
  16. if (timeout.timestamp > now) {
  17. timeout.reschedule(timeout.timestamp - now);
  18. } else {
  19. timeout.fireNow();
  20. }
  21. };
  22. Timeout.prototype.reschedule = function (interval) {
  23. this.clear();
  24. this.timer = setTimeout(Timeout.fired, clamp(interval), this);
  25. };
  26. Timeout.prototype.fireNow = function () {
  27. this.clear();
  28. this.cb.apply(this.thisArg, this.args);
  29. };
  30. Timeout.prototype.fireAt = function (timestamp) {
  31. this.timestamp = timestamp;
  32. this.reschedule(timestamp - Date.now());
  33. };
  34. Timeout.prototype.fireIn = function (interval) {
  35. this.timestamp = Date.now() + interval;
  36. this.reschedule(interval);
  37. };
  38. Timeout.prototype.clear = function () {
  39. if (this.timer) {
  40. clearTimeout(this.timer);
  41. this.timer = null;
  42. }
  43. };
  44. function Interval(cb, args, thisArg) {
  45. var that = this;
  46. var callback = function () {
  47. that.timeout.fireIn(that.interval);
  48. cb.apply(that.timeout.thisArg, that.timeout.args);
  49. };
  50. this.timeout = new Timeout(callback, args, thisArg);
  51. this.interval = null;
  52. }
  53. Interval.prototype.fireEvery = function (interval) {
  54. this.interval = interval;
  55. this.timeout.fireIn(interval);
  56. };
  57. Interval.prototype.clear = function () {
  58. this.timeout.clear();
  59. };
  60. exports.Timeout = Timeout;
  61. exports.Interval = Interval;
  62. exports.setTimeoutAt = function (cb, timestamp) {
  63. var args = [];
  64. for (var i = 2; i < arguments.length; i += 1) {
  65. args.push(arguments[i]);
  66. }
  67. var timer = new Timeout(cb, args, this);
  68. timer.fireAt(timestamp);
  69. return timer;
  70. };
  71. exports.setTimeout = function (cb, interval) {
  72. var args = [];
  73. for (var i = 2; i < arguments.length; i += 1) {
  74. args.push(arguments[i]);
  75. }
  76. var timer = new Timeout(cb, args, this);
  77. timer.fireIn(interval);
  78. return timer;
  79. };
  80. exports.setInterval = function (cb, interval) {
  81. var args = [];
  82. for (var i = 2; i < arguments.length; i += 1) {
  83. args.push(arguments[i]);
  84. }
  85. var timer = new Interval(cb, args, this);
  86. timer.fireEvery(interval);
  87. return timer;
  88. };
  89. exports.clearTimeout = exports.clearInterval = function (timer) {
  90. if (timer && typeof timer.clear === 'function') {
  91. timer.clear();
  92. }
  93. };