为什么setInterval调用不会因前4次执行而受到限制?

问题描述 投票:2回答:4

众所周知,JavaScript中的超时受到限制every 4ms on an active tab and every 1000ms on an inactive one。此行为可能会略有变化,具体取决于浏览器和配置,但通常是相同的。

为了完整起见,我在这里引用相关部分:

超时限制为> = 4ms

在现代浏览器中,当由于回调嵌套(其中嵌套级别至少是某个深度)或者在一定数量的连续间隔之后触发连续调用时,setTimeout() / setInterval()调用被限制为每4ms最少一次。

我想通过在默认Chrome实例上使用此代码段向某人证明:

let beforeStartingTheInterval = Date.now();
let intervalId = setInterval(()=>{ 
  let msPassed = Date.now()-beforeStartingTheInterval;
  if (msPassed > 20) clearInterval(intervalId); // stop after 20 ms
  console.log( msPassed + "ms have passed after starting the interval")
  }
,0);

几乎每次我运行该代码时,我都得到了这个输出:

1ms have passed after starting the interval
2ms have passed after starting the interval
3ms have passed after starting the interval
4ms have passed after starting the interval
8ms have passed after starting the interval
12ms have passed after starting the interval
16ms have passed after starting the interval
20ms have passed after starting the interval

可以看出,间隔(通常)前四次每毫秒运行一次,之后每隔> = 4ms。

为什么在前4次执行中,呼叫没有被限制?我期待这个输出:

4ms have passed after starting the interval
8ms have passed after starting the interval
12ms have passed after starting the interval
16ms have passed after starting the interval
20ms have passed after starting the interval

或者至少有一个在任何两次执行之间至少有4ms(即使是第一次执行)

javascript browser setinterval throttling
4个回答
1
投票

为什么在前4次执行中,呼叫没有被限制?

我想应该问的第一个问题是为什么计时器会被限制?

那么一些简单的事情可能就是这样的短暂运行计时器

1)难以实现,因为您必须使用硬件计时器或检查循环内的时间,以便能够准确地计算循环必须非常快地运行。

2)消耗大量电池/计算时间

3)可能根本不需要,因为显示器大约每60fps更新一次,即每16ms一次,所以如果你使用快速运行的计时器,你实际上看不到那个速度的输出。

接下来的问题可能是为什么一个人会使用这么短的计时器呢?

实际上有几个很好的理由:

1)在a)当前代码块之后推迟动作,取React的setState为例b)DOM重新渲染

2)在主线程上“异步”执行长时间运行的任务,而不阻塞UI,通过释放它一段时间。

因此,在调整计时器时间时,浏览器会出现问题:

如果它钳住例如setState 4ms,页面整体加载速度可能较慢。但是,如果它没有限制不必要地快速运行的setInterval,则会浪费用户电池(这些天大多数用户都在移动设备上)。

因此,浏览器非常快速地执行一些定时器是有道理的,这样setTimeout(deferred, 0)可以立即执行,但之后会被限制几次,以减少错误制作渲染定时器/长时间运行算法的负面影响。

“5次”之后的“4ms”可能是该考虑的平衡结果。


0
投票

答案是在documentation that you linked to(强调我的)

在Chrome和Firefox中,连续第五次回拨呼叫被限制; Safari在第6次通话时锁定;在Edge中它是第3个。 Gecko在版本56中开始像这样处理setInterval()(它已经使用setTimeout()执行此操作;请参见下文)。


0
投票

在搜索了一些网页后,我发现这是一个HTML5 standard

注意:定时器可以嵌套;然而,在五个这样的嵌套定时器之后,间隔被强制为至少4毫秒。


0
投票

https://humanwhocodes.com/blog/2011/12/14/timer-resolution-in-browsers/

大多数浏览器也会根据不同的条件进行某种定时器限制。目的是在适当的时候节省电池 - 从理论上讲,您要么不会注意到差异,要么愿意交换以改善笔记本电脑或移动设备的电池寿命。以下是计时器分辨率更改的一些情况:

© www.soinside.com 2019 - 2024. All rights reserved.