我知道由于浏览器计时器不准确,目前的差异可以忽略不计,但为了了解其他情况:是否有支持 setInterval 和 setTimeout 的浏览器,但需要将整数值作为延迟传递给它们?
或者,换句话说,是这样的:
setInterval(animate,50/3);
跨浏览器兼容吗?
setInterval(animate,17);
绝对安全
(正如 RobG 指出的那样,我没有提供对 DOM/JS 桥接规则本身的参考,他敦促谨慎。FWIW,我相信——但没有提及最终声明——
ToInteger
是 部分接口桥。这是一个 jsfiddle 显示超时作为字符串、浮点数和整数(与 JS 中的浮点数相同类型)传递,在 FF8 和 IE9 中工作正常。欢迎反馈。)
这是因为 DOM 接口只接受整数 用于
setTimeout/setInterval
中的延迟——是的,这些是在 DOM 中定义的,而不是在 ECMAScript 中定义的。延迟值首先被适当地转换为整数值(并且在这方面调用[JS-internal]ToInteger
函数执行截断*)。
但是,示例数字实际上会产生 略有不同的结果(尽管可能不明显):-)
这是因为,
50/3
(16.66andsomemore
-> 16
) 和 17
指定不同的超时时间.
快乐的编码。
*
ToInteger
定义为sign(number) * floor(abs(number))
,不包括特殊情况。请参阅第 5 版 ECMAScript 规范的第 9.4 节。
Javascript 在浮点数和整数之间没有真正的区别,并且在引擎盖下是相同的数据类型。
1
和 1.0
在内存中一点一点地相同。
因此,是的,您可以传递分数值而不会出现任何实际问题。它是完全有效的 JavaScript。即使它确实需要一个整数,它也更有可能简单地默默地为你四舍五入。
但不要指望它是准确的! 由于回调调度的低粒度,
0.1
、1
甚至 4.87
的时间都可能在非常接近同一时间触发。
我想第二个参数将被评估为一个表达式,只要它返回一个数字它就会起作用。它似乎适用于 chrome。只要确保你不除以零!
这些函数需要毫秒。我怀疑您能否期望任何超过 10 毫秒的精度,并且浏览器强制计时器限制。
Firefox 不介意十进制值。您可以在您感兴趣的任何其他浏览器中测试。
这取决于,取决于参数
delay
是否转换为整数,是否使用累积延迟[^1]策略,取决于您是否使用电池供电的设备以及省电模式。
测试
setInterval
1000/15~=66.6667 延迟,60s 持续时间,保持页面始终可见(不切换到后台,不关闭屏幕),使用以下浏览器:
看CodePensetInterval实际区间测试
setInterval
的实际平均间隔刻度
场合\平台 | Windows 浏览器 | 安卓浏览器 | macOS 浏览器 | iOS 浏览器 | Windows 火狐 | 安卓火狐 |
---|---|---|---|---|---|---|
页面可见 | 66.01 | 66.01 | 66.69 | 78.45 | 66.67 | |
页面可见(电池省电模式) | 66.01 | 66.01 | 89.76 | 78.36 | 66.68 | |
页面隐藏 | ||||||
隐藏页面(电池省电模式) |
根据上面的测试结果,我可以判断的是:
Chrome 的 setInterval 会
floor()
参数延迟,但它使用自我校准[^2] 策略来及时保持滴答声,目前忽略 Batter Saver Mode。
Safari 的 setInterval 取决于低功耗模式的状态,它支持分数延迟并使用自校准策略来及时保持滴答声,但是如果低功耗模式开启,则会发生累积延迟效应,因此分数延迟无济于事.
Windows Firefox的setInterval采用累积延迟策略,而Android Firefox的setInterval采用自校准策略。
脚注:
[^1]:累积延迟意味着平均滴答间隔将明显大于参数
delay
.
[^2]:自校准意味着平均滴答间隔可以非常接近参数
delay
.