setInterval 的持续时间

Duration of setInterval

我创建了一个简单的函数,它在 3 秒内将值从 0 计数到某个值。

这里是 fiddle - https://jsfiddle.net/ar6akv5z/ 和片段:

var number = document.querySelector('.number');
var button = document.querySelector('button');

button.addEventListener('click', function() {
    counting(number, 2500);
})

function counting(elem, value) {
 var count = 0;
 var timerId = setInterval(function() {
  if (++count == value) clearInterval(timerId);
  elem.innerHTML = count;
 }, 3000/value);
}
<span class="number">0</span>
<button>Go</button>

但是函数的持续时间超过了3秒。 你能解释一下为什么会这样或者告诉我我的错误吗?

谢谢,对不起我的英语

计时器的最小间隔受制于 an algorithm 指定的是 HTML5 规范(最初它在现已失效的计时器规范中),以防止计时器触发得太快。当定时器调度定时器时(本质上就是setInterval所做的),一旦嵌套达到五层,如果请求的定时器间隔<4ms,则设置为4ms:

  1. If nesting level is greater than 5, and timeout is less than 4, then increase timeout to 4.

由于您告诉它在每次计时器触发时加 1,而且它很快开始每 4 毫秒触发一次(最多),因此需要 4 * 2500 = 10000 毫秒(10 秒)才能完成。

您可以在下面更新的代码段中看到这个平均延迟,它用回调之间的平均时间替换了计数器:

if (!Date.now) {
  Date.now = function() {
    return +new Date();
  };
}
var number = document.querySelector('.number');
var button = document.querySelector('button');
var sum = 0;
var last = null;

button.addEventListener('click', function() {
    counting(number, 2500);
})

function counting(elem, value) {
 var count = 0;
  last = Date.now();
 var timerId = setInterval(function() {
   var now = Date.now();
   sum += now - last;
   last = now;
  if (++count == value) clearInterval(timerId);
  elem.innerHTML = sum / count;
 }, 3000/value);
}
<span class="number">0</span>
<button>Go</button>

setTimeoutsetInterval 规定了最短延迟。来自 MDN

Reasons for delays longer than specified

Nested timeouts forced to >=4ms

Historically browsers implement setTimeout() "clamping": successive setTimeout() calls with delay smaller than the "minimum delay" limit are forced to use at least the minimum delay. The minimum delay, DOM_MIN_TIMEOUT_VALUE, is 4 ms (stored in a preference in Firefox: dom.min_timeout_value), with a DOM_CLAMP_TIMEOUT_NESTING_LEVEL of 5.

In fact, 4 ms is specified by the HTML5 spec and is consistent across browsers released in 2010 and onward. Prior to (Firefox 5.0 / Thunderbird 5.0 / SeaMonkey 2.2), the minimum timeout value for nested timeouts was 10 ms.

因此,即使您指定 3000/2500 = 1.2 作为间隔时间,它的作用就好像您使用 4 作为间隔时间一样。