简体   繁体   English

将小数延迟传递给 setInterval 或 setTimeout 是否安全?

[英]Is it safe to pass setInterval or setTimeout a fractional delay?

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?我知道由于浏览器计时器不准确,目前的差异可以忽略不计,但为了了解,如果没有别的:是否有支持 setInterval 和 setTimeout 的浏览器,但需要将 integer 值作为延迟传递给它们?

Or, rephrased with examples, is this:或者,换句话说,是这样的:

setInterval(animate,50/3);

as cross-browser compatible as this?像这样跨浏览器兼容?

setInterval(animate,17);

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.) (正如RobG所指出的那样,我没有提供对DOM / JS桥接规则本身的引用,并且他敦促谨慎。我相信FWIW - 但没有提到最终状态 - ToInteger 接口桥的一部分。这是一个jsfiddle,显示超时传递为字符串,浮点数和积分(与JS中的浮点类型相同),在FF8和IE9中工作正常。欢迎反馈。)

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. 这是因为DOM接口只接受 setTimeout/setInterval延迟的整数 - 是的,这些是在DOM中定义的,而不是在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 *). 首先将延迟值适当地转换为整数值(在这方面,调用[JS-internal] ToInteger函数执行截断 *)。

However, the example numbers will actually yield slightly different results (although it might not be noticable) :-) 但是,示例数字实际上会产生略微不同的结果 (尽管可能不是很明显):-)

This is because, 50/3 ( 16.66andsomemore -> 16 ) and 17 specify different timeouts . 这是因为, 50/316.66andsomemore16.66andsomemore - > 16 )和17 指定不同的超时

Happy coding. 快乐的编码。


* ToInteger is defined as sign(number) * floor(abs(number)) , excluding special cases. * ToInteger定义为sign(number) * floor(abs(number)) ,不包括特殊情况。 See Section 9.4 of the 5th Edition ECMAScript specification. 请参见第5版ECMAScript规范的第9.4节。

Javascript makes no real distinction between floating point numbers and integers, and are the same data type under the hood. Javascript在浮点数和整数之间没有真正的区别,并且在引擎盖下是相同的数据类型。 1 and 1.0 are bit for bit identical in memory. 11.0在内存中位相同。

Therefore yes, you can pass a fractional value without any real issues. 因此,是的,你可以传递一个小数值,没有任何实际问题。 It's perfectly valid JavaScript. 这是完全有效的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 even 4.87 will all probably fire at very close to the same time due to the low granularity of the callback scheduling. 的时间0.11甚至4.87将非常接近同一时间都有可能发生火警时,回调调度粒度小。

It depends, depends on whether argument delay will be converted to integer, whether cumulative-delay [^1] strategy will be used, depends on whether you are using a battery-powered device and power saving mode is on.这取决于参数delay是否会转换为 integer,是否会使用 cumulative-delay [^1]策略,取决于您是否使用电池供电的设备以及省电模式是否开启。

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: test setInterval with 1000/15~=66.6667 delay, 60s duration, 保持页面一直可见(不切换到后台,不关闭屏幕),使用以下浏览器:

  • Windows Chrome 108 Windows 铬 108
  • Android Chrome 107 Android 铬 107
  • iOS Safari 16.0 iOS Safari 16.0
  • Windows Firefox 107 Windows Firefox 107
  • Android Firefox 108 Beta Android Firefox 108 测试版

see CodePen setInterval actual interval test看CodePen setInterval实际间隔测试

Actual average interval tick of setInterval setInterval的实际平均间隔tick

occasion \ platform场合\平台 Windows Chrome Windows 铬 Android Chrome Android 铬 macOS Safari苹果电脑 Safari iOS Safari iOS Safari Windows Firefox Windows Firefox Android Firefox Android Firefox
page visible页面可见 66.01 66.01 66.01 66.01 66.69 66.69 78.45 78.45 66.67 66.67
page visible (battery power saving mode)页面可见(电池省电模式) 66.01 66.01 66.01 66.01 89.76 89.76 78.36 78.36 66.68 66.68
page hidden页面隐藏
page hidden (battery power saving mode)页面隐藏(电池省电模式)

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. Chrome 的 setInterval 将floor()参数延迟,但它使用自校准[^2]策略来及时保持滴答声,目前忽略 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. Safari 的 setInterval 依赖于 Low Power Mode 的 state,它支持小数延迟并使用自校准策略来保持时间的滴答,但如果 Low Power Mode 打开,则会发生累积延迟效应,小数延迟就无济于事了。

Windows Firefox's setInterval uses cumulative-delay strategy,while Android Firefox's setInterval uses self-calibration strategy. Windows Firefox 的setInterval 使用累积延迟策略,而Android Firefox 的setInterval 使用自校准策略。

Footnote:脚注:

[^1] : cumulative-delay means average tick interval will be obviously larger than argument delay . [^1] : cumulative-delay 意味着平均滴答间隔将明显大于参数delay

[^2] : self-calibration means average tick interval can be very close to argument delay . [^2] :自校准意味着平均滴答间隔可以非常接近参数delay

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. 它似乎适用于chrome。 Just make sure you don't divide by zero! 只要确保你不要除以零!

These functions expect milliseconds. 这些函数需要几毫秒。 I doubt you could expect any accuracy greater than 10ms, and browsers enforce timer restrictions . 我怀疑你可以期待任何超过10毫秒的准确度,并且浏览器强制执行计时器限制

Firefox doesn't mind decimal values. Firefox并不介意十进制值。 You can test in any other browsers you're curious about. 可以在任何其他您感兴趣的浏览器中进行测试

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM