通过 setInterval 或 setTimeout 小数延迟是否安全?

问题描述 投票:0回答:5

我知道由于浏览器计时器不准确,目前的差异可以忽略不计,但为了了解其他情况:是否有支持 setInterval 和 setTimeout 的浏览器,但需要将整数值作为延迟传递给它们?

或者,换句话说,是这样的:

setInterval(animate,50/3);

跨浏览器兼容吗?

setInterval(animate,17);
javascript cross-browser settimeout setinterval
5个回答
10
投票

绝对安全

(正如 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 节。


4
投票

Javascript 在浮点数和整数之间没有真正的区别,并且在引擎盖下是相同的数据类型。

1
1.0
在内存中一点一点地相同。

因此,是的,您可以传递分数值而不会出现任何实际问题。它是完全有效的 JavaScript。即使它确实需要一个整数,它也更有可能简单地默默地为你四舍五入。

但不要指望它是准确的! 由于回调调度的低粒度,

0.1
1
甚至
4.87
的时间都可能在非常接近同一时间触发。


0
投票

我想第二个参数将被评估为一个表达式,只要它返回一个数字它就会起作用。它似乎适用于 chrome。只要确保你不除以零!


0
投票

这些函数需要毫秒。我怀疑您能否期望任何超过 10 毫秒的精度,并且浏览器强制计时器限制

Firefox 不介意十进制值。您可以在您感兴趣的任何其他浏览器中测试


0
投票

这取决于,取决于参数

delay
是否转换为整数,是否使用累积延迟[^1]策略,取决于您是否使用电池供电的设备以及省电模式。

测试

setInterval
1000/15~=66.6667 延迟,60s 持续时间,保持页面始终可见(不切换到后台,不关闭屏幕),使用以下浏览器:

  • Windows Chrome 108
  • 安卓 Chrome 107
  • iOS 浏览器 16.0
  • Windows 火狐 107
  • Android Firefox 108 测试版

看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
.

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