向 setInterval 或 setTimeout 传递小数延迟是否安全?
我知道由于浏览器计时器不准确,目前差异可以忽略不计,但为了了解知识,如果没有其他原因:是否有任何浏览器支持 setInterval 和 setTimeout,但要求它们传递一个整数值作为延迟?
或者,用示例重新表述,是这样的:
setInterval(animate,50/3);
像这样跨浏览器兼容吗?
setInterval(animate,17);
I know that the difference would currently be negligible due to inaccurate browser timers, but for the sake of knowledge if nothing else: is there any browser that supports setInterval and setTimeout, but requires that they be passed an integer value as a delay?
Or, rephrased with examples, is this:
setInterval(animate,50/3);
as cross-browser compatible as this?
setInterval(animate,17);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
这是绝对安全的。
(正如 RobG 指出的那样,我没有提供 DOM/JS 桥接规则本身的参考,他敦促谨慎行事。FWIW,我相信 - 但没有提到最终的声明 -
ToInteger
是接口桥的一部分。这是一个 jsfiddle 显示超时传递为一个字符串,一个float 和一个整型(与 JS 中的 float 类型相同),在 FF8 和 IE9 中运行良好。欢迎反馈。)这是因为 DOM 接口仅接受整数作为
setTimeout/setInterval
中的延迟 --是的,这些是在 DOM 中定义的,而不是在 ECMAScript 中定义的。首先将延迟值适当地转换为整数值(在这方面,调用 [JS 内部]ToInteger
函数来执行截断*)。然而,示例数字实际上会产生略有不同的结果(尽管可能不明显):-)
这是因为,
50/3
(16.66andsomemore< /code> ->
16
) 和17
指定不同的超时。快乐编码。
*
ToInteger
定义为sign(number) * Floor(abs(number))
,特殊情况除外。请参阅第 5 版 ECMAScript 规范第 9.4 节。It is perfectly safe.
(As RobG points out, I haven't provide a reference to the DOM/JS bridge rules themselves and he urges caution. FWIW, I believe -- but have no reference to conclusively state -- that
ToInteger
is part of the interface bridge. Here is a jsfiddle showing the timeout being passed as a string, a float, and an integral (same type as float in JS) which works fine in FF8 and IE9. Feedback welcome.)This is because the DOM interface only accepts integers for the delay in
setTimeout/setInterval
-- yup, these are defined in the DOM, not in ECMAScript. The delay value is appropriately converted to an integral value first (and in this aspect the [JS-internal]ToInteger
function is invoked which performs a truncation*).However, the example numbers will actually yield slightly different results (although it might not be noticable) :-)
This is because,
50/3
(16.66andsomemore
->16
) and17
specify different timeouts.Happy coding.
*
ToInteger
is defined assign(number) * floor(abs(number))
, excluding special cases. See Section 9.4 of the 5th Edition ECMAScript specification.JavaScript 对浮点数和整数没有真正的区别,并且在底层是相同的数据类型。
1
和1.0
在内存中是逐位相同的。因此,是的,您可以传递小数值而不会出现任何实际问题。这是完全有效的 JavaScript。即使它确实需要一个整数,它也更有可能简单地、默默地为您舍入它。
但不要指望它是准确的!
0.1
、1
甚至4.87
的时间都可能由于回调调度的粒度较低,因此会在非常接近的时间触发。Javascript makes no real distinction between floating point numbers and integers, and are the same data type under the hood.
1
and1.0
are bit for bit identical in memory.Therefore yes, you can pass a fractional value without any real issues. It's perfectly valid JavaScript. And even if it did require an integer, it's more likely it would simply and silently round it down for you.
But don't expect it to be accurate! A time of
0.1
,1
or even4.87
will all probably fire at very close to the same time due to the low granularity of the callback scheduling.我想第二个参数将被计算为一个表达式,只要它返回一个数字就可以工作。它似乎可以在 Chrome 中使用。只要确保你没有被零除即可!
I would imagine that the second parameter would be evaluated as an expression and as long as it returns a number it will work. It seems to work in chrome. Just make sure you don't divide by zero!
这些函数需要毫秒。我怀疑您可以期望任何大于 10 毫秒的精度,并且浏览器强制执行计时器限制。
Firefox 不介意小数值。您可以在您感兴趣的任何其他浏览器中进行测试。
These functions expect milliseconds. I doubt you could expect any accuracy greater than 10ms, and browsers enforce timer restrictions.
Firefox doesn't mind decimal values. You can test in any other browsers you're curious about.
这取决于,取决于参数
delay
是否转换为整数,是否使用累积延迟[^1]策略,取决于您是否使用电池供电的设备并且省电模式已开启。使用以下浏览器测试
setInterval
,延迟 1000/15~=66.6667,持续时间 60 秒,保持页面始终可见(不切换到后台,不关闭屏幕):请参阅 CodePen setInterval 实际间隔测试
的实际平均间隔刻度
setInterval
场合\平台根据上面的测试结果,我可以看出:
Chrome的setInterval会
floor()
参数延迟,但它使用自校准[^2]策略来保持tick目前,及时忽略节电模式。Safari 的 setInterval 取决于低功耗模式的状态,它支持分数延迟并使用自校准策略来及时保持滴答声,但如果低功耗模式打开,则会发生累积延迟效应,使得分数延迟无济于事。
Windows Firefox 的 setInterval 采用累积延迟策略,而 Android Firefox 的 setInterval 采用自校准策略。
脚注:
[^1]:累积延迟意味着平均刻度间隔将明显大于参数
延迟
。[^2]:自校准意味着平均刻度间隔可以非常接近参数
延迟
。It depends, depends on whether argument
delay
is converted to integer, whether cumulative-delay[^1] strategy is used, depends on whether you are using a battery-powered device and power saving mode is on.Test
setInterval
with 1000/15~=66.6667 delay, 60s duration, keep page visible all the time (without switching to background, without screen off), with the following browsers:see CodePen setInterval actual interval test
Actual average interval tick of
setInterval
According to the test result above, what I can tell is:
Chrome's setInterval will
floor()
argument delay, but it use self-calibration[^2] strategy to keep ticks in time, currently ignores Batter Saver Mode.Safari's setInterval depends on state of Low Power Mode, it supports fractional delay and use self-calibration strategy to keep ticks in time, but if Low Power Mode is on then cumulative-delay effect happens such that a fractional delay just doesn't help.
Windows Firefox's setInterval uses cumulative-delay strategy,while Android Firefox's setInterval uses self-calibration strategy.
Footnote:
[^1]: cumulative-delay means average tick interval will be obviously larger than argument
delay
.[^2]: self-calibration means average tick interval can be very close to argument
delay
.