JavaScript setTimeout如此不准确的原因是什么?

Tom*_*ado 35 javascript settimeout

我在这里得到了这个代码:

var date = new Date();
setTimeout(function(e) {
    var currentDate = new Date();
    if(currentDate - date >= 1000) {
         console.log(currentDate, date);
         console.log(currentDate-date);
    }
    else {
       console.log("It was less than a second!");
       console.log(currentDate-date);
    }
}, 1000);
Run Code Online (Sandbox Code Playgroud)

在我的计算机中,它总是正确执行,在控制台输出中为1000.有兴趣在其他计算机,相同的代码,超时回调开始不到一秒钟,差异currentDate - date在980和998之间.

我知道存在解决这种不准确性的库(例如,Tock).

基本上,我的问题是:原因setTimeout什么,因为在给定的延迟中不会触发?可能是计算机速度太慢而且浏览器会自动尝试适应缓慢并且之前触发事件?

PS:以下是Chrome JavaScript控制台中执行的代码和结果的屏幕截图:

在此输入图像描述

p.s*_*w.g 22

它不应该特别准确.有许多因素限制浏览器执行代码的时间; MDN引用:

除了"钳制"之外,当页面(或OS /浏览器本身)忙于其他任务时,超时也可能在以后触发.

换句话说,setTimeout通常实现的方式,只是意味着在给定的延迟之后执行,并且一旦浏览器的线程可以自由执行它.

但是,不同的浏览器可能以不同的方式实现它.以下是我做过的一些测试:

var date = new Date();
setTimeout(function(e) {
    var currentDate = new Date();
    console.log(currentDate-date);
}, 1000);

// Browser Test1 Test2 Test3 Test4
// Chrome    998  1014   998   998
// Firefox  1000  1001  1047  1000
// IE 11    1006  1013  1007  1005
Run Code Online (Sandbox Code Playgroud)

也许Chrome的<1000次可归因于该Date类型的不准确性,或者可能是Chrome使用不同的策略来决定何时执行代码 - 也许它试图将其装入最近的时段,即使超时延迟尚未完成.

简而言之,setTimeout如果您期望可靠,一致,毫秒级的时序,则不应使用.

  • 简而言之,如果您期望可靠、一致、毫秒级的任何东西,则不应使用“JavaScript”。该语言确实没有其他选择。 (2认同)

Nie*_*jes 19

通常,当尝试执行精度高于50 ms的事物时,计算机程序非常不可靠.这样做的原因是,即使在octacore超线程处理器上,操作系统通常也会处理数百个进程和线程,有时甚至是数千个或更多.操作系统通过调度所有这些来完成所有多任务工作,以便一个接一个地获得一片CPU时间,这意味着他们最多只需要几毫秒的时间来做他们的事情.

这意味着,如果你设置一个1000毫秒的超时,那么当前的浏览器进程甚至不会在那个时间点运行的可能性很小,所以浏览器在1005,1010或之前没有注意到这是完全正常的.甚至1050毫秒它应该执行给定的回调.

通常这不是问题,它发生了,并且它很少是最重要的.如果是,所有的操作系统供应内核级的定时器,远远超过1毫秒精确,并允许开发人员在执行代码正是在正确的时间点.但是,作为一个沙盒很大的环境,JavaScript无法访问这样的内核对象,并且浏览器不会使用它们,因为它理论上可以让某人从网页内部攻击操作系统稳定性,通过仔细构建使其他人挨饿的代码线程淹没了许多危险的计时器.

至于为什么测试产生980我不确定 - 这将取决于你正在使用哪个浏览器以及哪个JavaScript引擎.然而,我可以完全理解浏览器是否只是手动向下校正系统负载和/或速度,确保"平均延迟仍然是正确的时间" - 从沙盒原理到仅仅是很有意义接近所需的时间而不会给系统的其他部分带来负担.


Mat*_*ics 7

如果我误解了这些信息,请有人纠正我:

根据John Resig帖子,关于跨平台的性能测试的不准确性(强调我的)

随着系统时间不断向下舍入到最后查询时间(每个间隔约15毫秒),性能结果的质量严重受损.

因此,与系统时间相比,两端最多可以有15毫秒的软糖.

  • 这是问题的一个方面.另一个问题是浏览器的异步性质,因此根据队列中的其他内容,可以暂停超时以处理其他作业. (2认同)