通常情况下,浏览器在某些情况下会修改setInterval使用的实际时间间隔,甚至超过最小钳位.例如,我有以下代码:
function start() {
    window.setInterval(function() {
        update();
    },1);
}

lastTime = new Date;
numFrames = 0;
lastFrames = 0;

function update() {
    numFrames++;
    if (new Date - lastTime >= 1000) {
        lastFrames = numFrames;
        numFrames = 0;
        lastTime = new Date;
    }
}

在这里,lastFrames将为我们提供大约过去第二帧的帧数.在Chrome,Firefox和Safari中使用时,此代码不会在一毫秒内运行.当然,每个浏览器在setInterval调用之间都有一个任意的最小时间,所以这是可以预料的.但是,随着页面继续运行,即使选项卡仍处于焦点,帧速率也将继续降低.我发现修复此问题的唯一方法是让浏览器执行某些操作.沿着这些方向的东西似乎使浏览器尽可能快地运行setInterval:

function start() {
    window.setInterval(function() {
        update();
    },1);
}

lastTime = new Date;
numFrames = 0;
lastFrames = 0;

function update() {
    numFrames++;
    if (new Date - lastTime >= 1000) {
        lastFrames = numFrames;
        numFrames = 0;
        lastTime = new Date;
    }

    //doIntensiveLoop,processing,etc.
}

因此,我的问题是:浏览器寻找什么来证明运行setInterval更接近我的要求?

编辑:HTML5规范说,浏览器不应允许setInterval以低于4毫秒的间隔运行.

解决方法

我想首先,我们必须问自己我们对Interval函数的期望:

>他们必须保持上下文:你无法可靠地增加一个计数器的间隔将是非常灾难性的
>它们应该执行函数中的任何内容,该函数优先于执行间隔(此处相同,定时器必须在我们再次递增之前上升)
>它应该与我们的其余js代码有一个单独的执行堆栈(我们不想等待那些定时器完成他们的业务,直到其余的开始执行);
>他们应该知道他们所处的环境,无论它有多大(我们希望能够在我们的计时器函数中使用jQuery).

因此,正如Matt Greer所述,Intervals的设计并不精确,这主要是因为我们并不真正期望它们是精确的,而是在给定时间可靠地执行代码.

如果您查看Chromium实现,您将看到setTimeout和setInterval的实现基于DOMTimer::install,它将传递执行上下文,操作以及计时器是否为单击

这将传递给RunloopTimer,它在系统定时器(as you see here)的帮助下执行循环

(顺便说一下,铬的间隔至少安装10毫秒,你可以看到here)

该操作的每次执行都是handled here,在上次执行超过或低于某个时间限制的时间内没有任何断言.

相反,它只通过减慢使用过多资源/在给定时间间隔内运行速度太慢的定时器来断言Timer嵌套级别does not get too deep:

if (m_nestingLevel >= maxTimernestingLevel)
            augmentRepeatInterval(minimumInterval - repeatInterval());
    }

augmentRepeatInterval只是为间隔添加更多毫秒:

void augmentRepeatInterval(double delta) { augmentFireInterval(delta); m_repeatInterval += delta; }

那么,我们可以得出什么结论呢?

>测量间隔或超时的时间精度是浪费时间.你应该和可以关心的事情是你没有为你想在函数中执行的东西设置太低的间隔.浏览器将尽最大努力及时执行间隔和超时,但不能保证准确的时间安排.
> Interval执行取决于环境,浏览器,实现,版本,上下文,操作本身等等.它并不准确,如果你想用setTimeout或setInterval编写精确的东西,你现在要么疯了,要么以后会发疯.
>您说在您的代码中,当您对函数添加大量执行时,计时器变得更加准确.这可能是出于不同的原因(可能会获得更多内存,更多独占cpu时间,更多工作人员等等).我对此很感兴趣,但是你没有提供执行繁重执行的代码.因此,如果你想要一些答案,请提供代码,因为没有它就很难假设.
>但不管是什么让你的间隔运行更及时,它在任何方面都不可靠.如果您开始在不同系统上进行测量,您很可能会得到各种各样的结果.

UPDATE

除此之外,浏览器JS引擎可以对未导致任何内容的代码进行优化(不执行,仅执行一次,以更好的方式执行).让我举一个基于你的例子(所有用铬执行的东西):

function start() {
  window.setInterval(function() {
    update();
  },1);
}

lastTime = new Date;
 numFrames = 0;
lastFrames = 0;

function update() {
  console.log(new Date() - lastTime);
  lastTime = new Date();
  for (var i=0; i < 1000000; i++) { var k = 'string' + 'string' + 'string' }
}

你会发现在你点击开始后的第一次执行需要很长时间,而进一步的执行则不会(至少在webkit中).这是因为迭代中的代码不会改变任何东西,浏览器会在第一次执行后识别出它并且不再执行它.

让我们看一下如果执行必须保持与外部变量的绑定(在本例中为kin),它会如何变化:

var k;

function update() {
  console.log(new Date() - lastTime);
  lastTime = new Date();
  for (var i=0; i < 1000000; i++) { k = 'string' + 'string' + 'string' }
}

好的,这里我们对执行时间有一些影响,但它仍然很快.浏览器知道for循环将始终执行相同的操作,但它会执行一次.那么,如果迭代确实创建了一个巨大的字符串呢?

var k;

function update() {
  console.log(new Date() - lastTime);
  lastTime = new Date();
  k = '';
  for (var i=0; i < 1000000; i++) { k += i.toString() }
}

这使得浏览器处于一个受伤的世界,因为它必须返回这个数百万字符的字符串.我们能让这更痛苦吗?

var k;

function update() {
  console.log(new Date() - lastTime);
  lastTime = new Date();
  k = '';
  for (var i=0; i < 1000000; i++) { k = ['hey','hey','hey'].join('') }
}

这个数组连接无法进行优化,几乎可以缓慢而痛苦地阻塞任何浏览器.

因此,在您的情况下,繁重的执行可能会导致更多内存被保留并立即被优化器释放.可能是新鲜空气的呼吸和额外的记忆以及闲置的cpu使你的功能快乐地跳起来,但正如我所说的那样,没有看到你繁重的执行代码就没有什么可靠的.

javascript – 浏览器如何确定setInterval应该使用的时间?的更多相关文章

  1. android – 在onLocationChanged中不能setInterval

    )我对样本的唯一更改是:如何更改onLocationChanged内的间隔?

  2. JavaScript学习笔记整理_setTimeout的应用

    下面小编就为大家带来一篇JavaScript学习笔记整理_setTimeout的应用。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  3. JavaScript中定时器setTimeout()和setInterval()的用法

    本文详细讲解了JavaScript中定时器setTimeout()和setInterval()的用法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  4. JavaScript setinterval延迟一秒解决方案

    这篇文章主要介绍了JavaScript setinterval延迟一秒解决方案,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下

  5. JavaScript 的setTimeout与事件循环机制event-loop

    这篇文章主要介绍了JavaScript 的setTimeout与事件循环机制event-loop,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下

  6. setInterval()和setTimeout()的用法和区别示例介绍

    setInterval()和setTimeout()想必大家并不陌生吧,接触js的朋友都知道的,不过还是有一些新手朋友对两者的用法不是很熟悉,下面简要的为大家介绍下

  7. 浅谈js的setInterval事件

    这篇文章主要介绍了js的setInterval方法的用法以及示例,非常的有用,这里推荐给小伙伴们

  8. React中使用setInterval函数的实例

    这篇文章主要介绍了React中使用setInterval函数的实例,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  9. JavaScript使用setTimeout实现倒计时效果

    这篇文章主要为大家详细介绍了JavaScript使用setTimeout实现倒计时效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. javascript中interval与setTimeOut的区别示例介绍

    这篇文章主要介绍了javascript中interval与setTimeOut的区别,需要的朋友可以参考下

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部