各浏览器的setInterval实现细节测试

如何以指定的帧速绘制动画?用setInterval来调度误差大吗?下面的测试会给出解答。

环境和设定

浏览器

  • Windows Chrome 108
  • Android Chrome 107
  • iOS Safari 16.0
  • Windows Firefox 107
  • Android Firefox 108 Beta

测试15fps的帧速(帧间隔毫秒为1000/15),测试持续60秒,期间页面一直保持显示状态(不切换到后台,不息屏)

测试代码

在线演示见CodePen setInterval actual interval test

Interval set: <span id="interval0">0</span><br/>
Average interval <span id="interval1">0</span><br/>
<script>
function main() {
  let interval = 1000 / 15;
  document.querySelector('#interval0').textContent = interval ;
  let span = document.querySelector('#interval1');
  let count = 0;
  let startTime = performance.now();
  let handle = setInterval(() => {
    let date = new Date();
    count++;
    let avgInterval = (performance.now() - startTime) / count;
    span.textContent = avgInterval.toFixed(2);
  }, interval);
}
document.addEventListener('DOMContentLoaded', main);
</script>

测试结果

setInterval的实测平均间隔

occasion \ platformWindows ChromeAndroid ChromemacOS SafariiOS SafariWindows FirefoxAndroid Firefox
page visible66.0166.0166.6978.4566.67
page visible (battery power saving mode)66.0166.0189.7678.3666.68
page hidden
page hidden (battery power saving mode)

解读

根据以上测试结果,我能得出的结论是:

Chrome的setInterval似乎对delay参数进行了floor()处理(不支持delay的小数部分),采取自校准策略使得调度较为准时(当参数delay为整数时调度不会顺延),似乎未针对省电模式切换策略。

Safari的setInterval分两种情况:非省电模式中支持delay参数的小数部分,采取自校准策略使得调度较为准时;省电模式中采取累积延迟策略(顺延)。

Windows Firefox的setInterval采取累积延迟策略,Android Firefox的setInterval采取自校准策略,两者似乎未针对省电模式切换策略。

这么乱,接下来怎么办

自校准策略和累积延迟策略的setInterval各有其适用场合,类似于对即时性要求高容许丢包的UDP协议和对准确要求高容许延迟的TCP协议适用与不同场景。

作者分别给出基于这两种策略的两套setInterval实现(见Gist setInterval implementations),使得前端开发者在不同的应用场景下选择不同策略的setInterval实现,当然开发者应优先检测浏览器的setInterval策略,如果合适则优先采用浏览器原生的setInterval。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值