setTimeout 不准时原因及 弥补办法

在使用 setTimeout() 时,一般都会比设定的时间要稍微长一点,即使是 setTimeout(fn, 0) 也不会立即执行。造成这种问题的根本原因是: 最小延迟时间

有很多因素会导致setTimeout的回调函数执行比设定的预期值更久,本节将讨论最常见的原因。

最小延时 >= 4ms

在浏览器中,setTimeout()/setInterval() 的每调用一次定时器的最小间隔是4ms,这通常是由于函数嵌套导致(嵌套层级达到一定深度),或者是由于已经执行的setInterval的回调函数阻塞导致的。例如:

function cb() { f(); setTimeout(cb, 0); }
setTimeout(cb, 0);
setInterval(f, 0);

在Chrome 和 Firefox中, 定时器的第5次调用被阻塞了;在Safari是在第6次;Edge是在第3次。Gecko 从这个版本 version 56开始对 setInterval() 开始采用这样的机制(setTimeout()已经实现,具体请参考以下内容)。

一直以来,不同浏览器中出现这种最小延迟的情况有所不同(例如Firefox) - 从其他地方调用了setInterval( ),或者在嵌套函数调用setTimeout( ) 时(嵌套级别达到特定深度时),都会出现超时延迟。

如果想在浏览器中实现0ms延时的定时器,你可以参考 这里 所说的{domxref("window.postMessage()")}}

大神手写低延迟DEMO

未被激活的tabs的定时最小延迟>=1000ms

为了优化后台tab的加载损耗(以及降低耗电量),在未被激活的tab中定时器的最小延时限制为1S(1000ms)。

Firefox 从version 5 (see bug 633421开始采取这种机制,1000ms的间隔值可以通过 dom.min_background_timeout_value 改变。Chrome 从 version 11 (crbug.com/66078)开始采用。

Android 版的Firefox对未被激活的后台tabs的使用了15min的最小延迟间隔时间 ,并且这些tabs也能完全不被加载。

当 Web Audio API AudioContext 正在被用来播放音频的时候,Firefox 50不会再限制后台tabs的加载。 后续的Firefox 51 版本修正了这个问题,即使在没有音频播放的情况下,也不再限制后台tabs的加载。这个解决了一些软件应用在后台tabs中播放基于文本的音频( note-based) 时,无法去同步音频和画面的问题。

追踪型脚本的最小延时限制

从Firefox 55版本开始,追踪型脚本(例如 谷歌分析,或者其他的一些被Firefox 的 TP lists 识别为追踪型脚本的 外链URL脚本)是重点限制加载的对象。在当前正在使用的页面中,这个节流限制的延时依然是4ms。但是在后台tabs中,这个最小延时限制是10000ms(10s),这个限制会在文档第一次加载后的30s后生效。

控制这些行为的属性包含以下这些:

  • dom.min_tracking_timeout_value: 4
  • dom.min_tracking_background_timeout_value: 10000
  • dom.timeout.tracking_throttling_delay: 30000

超时延迟

除了"最小延时"之外,定时器仍然有可能因为当前页面(或者操作系统/浏览器本身)被其他任务占用导致延时。 需要被强调是, 直到调用 setTimeout()的主线程执行完其他任务之后,回调函数和代码段才能被执行。例如:

function foo() {
  console.log('foo has been called');
}
setTimeout(foo, 0);
console.log('After setTimeout');

// After setTimeout
// foo has been called

出现这个结果的原因是,尽管setTimeout 以0ms的延迟来调用函数,但这个任务已经被放入了队列中并且等待下一次执行;并不是立即执行;队列中的等待函数被调用之前,当前代码必须全部运行完毕,因此这里运行结果并非预想的那样。

文章节选自:MDN

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端卡卡西呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值