【问题标题】:Is it safe to pass setInterval or setTimeout a fractional delay?传递 setInterval 或 setTimeout 分数延迟是否安全?
【发布时间】:2011-12-12 00:51:59
【问题描述】:

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

或者,换个例子,是这样的:

setInterval(animate,50/3);

像这样跨浏览器兼容?

setInterval(animate,17);

【问题讨论】:

  • 它的定义方式,第二个参数是“毫秒数”。现在,如果该数字应该是自然的,则没有定义......
  • @ŠimeVidas 定义完美。请参阅 DOM 规范 ;-)

标签: javascript cross-browser settimeout setinterval


【解决方案1】:

绝对安全。

(正如 RobG 指出的那样,我没有提供对 DOM/JS 桥接规则本身的参考,他敦促谨慎。FWIW,我相信——但没有提及最终状态——ToInteger 接口桥的一部分。这里是一个jsfiddle 显示超时被传递为一个字符串,一个浮点数和一个整数(与JS中的浮点数相同的类型),在FF8和IE9中可以正常工作。欢迎。)

这是因为the DOM interface only accepts integerssetTimeout/setInterval 中的延迟——是的,这些是在 DOM 中定义的,而不是在 ECMAScript 中。延迟值首先被适当地转换为整数值(在这方面,[JS-internal] ToInteger 函数被调用执行截断*)。

但是,示例数字实际上会产生略有不同的结果(尽管可能不明显):-)

这是因为,50/3 (16.66andsomemore -> 16) 和 17 指定了不同的超时时间

编码愉快。


*ToInteger定义为sign(number) * floor(abs(number)),特殊情况除外。请参阅第 5 版 ECMAScript 规范的第 9.4 节。

【讨论】:

  • 好的,所以这个规范描述的是 C(或其他不是 javascript)的实现,对吧?那么截断发生在javascript环境之外呢?
  • @skier88 从技术上讲,DOM 实现必须在 C 中——尽管我怀疑在大多数情况下是这样——但它确实将值限制为整数“长”。 JS 引擎有一个 [n inaccessible to user] 部分,它知道如何“与 DOM 对话”,它执行与 DOM 的转换。发布的链接仅涵盖 interface 合同。 ToInteger 函数是 ECMAScript 中定义的内部函数,我相信——但我可能错了——这个(或等效的)用于积分转换。
  • 是的,我知道语言可能会有所不同,它只是帮助我想出一个示例编程语言来可视化正在执行的代码级别。感谢您的回复 - 我可能早就应该下载规范了。
  • 我不会称之为“完全安全”。 HTML5 规范(不是标准)说“可选长超时”,所以给它一个整数,不要依赖其他人进行纠错。
  • @RobG 我仍然认为它非常安全——例如传递一个字符串,它不会崩溃,但也会通过ToInteger 进行转换——但是,因为我找不到关于实际DOM/JS 桥的参考,我无法反驳...这是jsfiddle
【解决方案2】:

Javascript 在浮点数和整数之间没有真正的区别,并且在底层是相同的数据类型。 11.0 在内存中是逐位相同的。

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

但不要指望它是准确的!0.11 甚至 4.87 的时间都可能会在非常接近同时触发,因为低回调调度的粒度。

【讨论】:

  • 谢谢,出于某种原因,我没有考虑数据类型。关于颗粒化的好处 - IIRC,它实际上通常像 15ms 一样糟糕。我真正关心的只是长时间运行间隔的(可能难以察觉的)漂移。
  • 漂移是真实的,这是我最近在使用它来计时音乐节拍时遇到的一个问题。这很糟糕。这是我的解决方案:alexwayne.tumblr.com/post/13744997785/accurateinterval 或者跳过散文并在此处获取我的原始代码:gist.github.com/1d99b3cd81d610ac7351
  • 11.0 在 JavaScript 语言中表示相同的 Number 值的事实在此无关紧要。问题是关于 setTimeout 函数的行为。请注意,此函数不是 JavaScript 语言的一部分。它是 HTML 标准中指定的浏览器功能。据我所知,如果提供非自然数作为第二个参数(如1.23),则行为是未定义的,这意味着由浏览器来实现此行为。
  • 全部正确。但在实践中,它要么将其四舍五入为整数,要么将其真正用作小数。无论哪种方式你都不知道。无论哪种方式,Is it safe to pass setInterval or setTimeout a fractional delay? 的答案都是非常明确的“是的,很好”。
  • 漂移setInterval 对我来说是真实的。它似乎以这样的方式实现,setInterval(fn, 1000) 意味着:在 1000 毫秒内安排对fn 的回调。当触发回调时,在当前时间的另外 1000 毫秒内安排另一个回调。因此,如果第一个回调实际上延迟了 1 毫秒或 2 毫秒(这种情况经常发生),那么您就永远失去了 2 毫秒。我的实现检测到这种漂移并在1000ms - 2ms 安排下一个回调,弥补回调运行有点晚的事实。
【解决方案3】:

我想第二个参数将被评估为一个表达式,只要它返回一个数字,它就可以工作。它似乎在铬中工作。只要确保你不被零除!

【讨论】:

    【解决方案4】:

    这些函数需要毫秒。我怀疑您是否可以期望任何大于 10 毫秒的精度,以及浏览器 enforce timer restrictions

    Firefox 不介意十进制值。你在任何其他你好奇的浏览器中can test

    【讨论】:

    • 感谢您的回复。如上所述,我关心的不是准确的时间,而是漂移(虽然它可能是难以察觉的)。
    猜你喜欢
    • 1970-01-01
    • 2020-09-10
    • 1970-01-01
    • 2012-10-30
    • 1970-01-01
    • 2022-01-25
    • 2011-11-05
    • 2015-04-23
    • 2017-06-28
    相关资源
    最近更新 更多