No setTimeout, No setInterval
如果你不得不使用setTimeout或者setInterval来实现动画,那么原因只能是你需要精确的控制动画。但我认为至少在现在这个时间点,高级浏览器、甚至手机浏览器的普及程度足够让你有理由有条件在实现动画时使用更高效的方式。
什么是高效
页面是每一帧变化都是系统绘制出来的(GPU或者CPU)。但这种绘制又和PC游戏的绘制不同,它的最高绘制频率受限于显示器的刷新频率(而非显卡),所以大多数情况下最高的绘制频率只能是每秒60帧(frame per second,以下用fps简称),对应于显示器的60Hz。60fps是一个最理想的状态,在日常对页面性能的测试中,60fps也是一个重要的指标,the closer the better。在Chrome的调试工具中,有不少工具都是用于衡量当前帧数:
接下来的工作中,我们将会用到这些工具,来实时查看我们页面的性能。
60fps是动力也是压力,因为它意味着我们只有16.7毫秒(1000 / 60)来绘制每一帧。如果使用setTimeout或者setInterval(以下统称为timer)来控制绘制,问题就来了。
首先,Timer计算延时的精确度不够。延时的计算依靠的是浏览器的内置时钟,而时钟的精确度又取决于时钟更新的频率(Timer resolution)。IE8及其之前的IE版本更新间隔为15.6毫秒。假设你设定的setTimeout延迟为16.7ms,那么它要更新两个15.6毫秒才会该触发延时。这也意味着无故延迟了 15.6 x 2 - 16.7 = 14.5毫秒。
16.7ms DELAY: |------------| CLOCK: |----------|----------| 15.6ms 15.6ms
所以即使你给setTimeout设定的延时为0ms,它也不会立即触发。目前Chrome与IE9+浏览器的更新频率都为4ms(如果你使用的是笔记本电脑,并且在使用电池而非电源的模式下,为了节省资源,浏览器会将更新频率切换至于系统时间相同,也就意味着更新频率更低)。
退一步说,假使timer resolution能够达到16.7ms,它还要面临一个异步队列的问题。因为异步的关系setTimeout中的回调函数并非立即执行,而是需要加入等待队列中。但问题是,如果在等待延迟触发的过程中,有新的同步脚本需要执行,那么同步脚本不会排在timer的回调之后,而是立即执行,比如下面这段代码:
function runForSeconds(s) { var start = +new Date(); while (start + s * 1000 > (+new Date())) {} } document.body.addEventListener("click", function () { runForSeconds(10); }, false); setTimeout(function () { console.log("Done!"); }, 1000 * 3);
如果在等待触发延迟的3秒过程中,有人点击了body,那么回调还是准时在3s完成时触发吗?当然不能,它会等待10s,同步函数总是优先于异步函数:
等待3秒延迟 | 1s | 2s | 3s |--->console.log("Done!"); 经过2秒 |----1s----|----2s----| |--->console.log("Done!"); 点击body后 以为是这样:|----1s----|----2s----|----3s----|--->console.log("Done!")--->|------------------10s----------------| 其实是这样:|----1s----|----2s----|------------------10s----------------|--->console.log("Done!");
John Resign有三篇关于Timer性能与准确性的文章: 1.Accuracy of JavaScript Time, 2.Analyzing Timer Performance, 3.How JavaScript Timers Work。从文章中可以看到Timer在不同平台浏览器与操作系统下的一些问题。
再退一步说,假设timer resolution能够达到16.7ms,并且假设异步函数不会被延后,使用timer控制的动画还是有不尽如人意的地方。这也就是下一节要说的问题。
查看本栏目更多精彩内容:http://www.bianceng.cnhttp://www.bianceng.cn/webkf/script/
以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索浏览器
, lm3s9b92
, opnet14.5
, 更新
, 延迟
, console
, 毫秒
, settimeout
, 浏览器延迟 渲染
, s实现动画
延时切换
高性能javascript、高性能javascript pdf、高性能的javascript、高性能javascript编程、高性能javascript txt,以便于您获取更多的相关知识。