如何在Chrome中的选项卡处于非活动状态时使setInterval也起作用? [英] How can I make setInterval also work when a tab is inactive in Chrome?

查看:1014
本文介绍了如何在Chrome中的选项卡处于非活动状态时使setInterval也起作用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 setInterval ,每秒运行一段代码30次。这个效果很好,但是当我选择另一个选项卡时(这样使得我的代码选项卡变为非活动状态),出于某种原因 setInterval 被设置为空闲状态。



我做了这个简化的测试用例( http://jsfiddle.net / 7f6DX / 3 / ):

  var $ div = $('div'); 
var a = 0;

setInterval(function(){
a ++;
$ div.css(left,a)
},1000/30);

如果您运行此代码然后切换到另一个选项卡,请等待几秒钟后返回当您切换到其他选项卡时,动画继续进行。因此,如果选项卡处于非活动状态,则动画不会每秒运行30次。这可以通过计算每秒调用 setInterval 函数的次数来确认 - 如果该选项卡处于非活动状态,则不会是30,而只会是1或2。 >

我猜这是通过设计完成的,以提高性能,但有什么办法可以禁用这种行为吗?这在我的场景中实际上是一个缺点。在大多数浏览器中,非活动选项卡的优先级较低,这会影响JavaScript计时器。如果您的转换值是使用帧间实际时间进行计算的,而不是每个间隔的固定增量,则不仅可以解决此问题,还可以解决此问题也可以使用 requestAnimationFrame ,因为如果处理器不是很忙的话它可以达到60fps。

以下是使用<$ c的动画属性转换的香草JavaScript示例$ c> requestAnimationFrame :

var targe t = document.querySelector('div#target')var startedAt,duration = 3000var domain = [-100,window.innerWidth] var range = domain [1] - domain [0] function start(){startedAt = Date.now ()updateAttribute(0)requestAnimationFrame(update)} function update(){let elapsedTime = Date.now() - startedAt //播放是介于0和1之间的值// 0是动画的开始和1的结束let playback = elapsedTime / duration updateTarget(playback)if(playback> 0&&回放< 1){//排队下一帧requestAnimationFrame(更新)} else {//等待一段时间,然后重新开始动画setTimeout(start,duration / 10)}} function updateTarget(playback){//取消注释下面一行以反转动画//播放= 1 - 播放//根据播放位置更新目标属性let position = domain [0] +(playback * range)target.style.left = position +'px'target.style.top = position +'px'target.style.transform ='scale('+ playback * 3 +')'} start()

  body {overflow:hidden;} div {position:absolute;  

< div id = target> ...这里我们去了< / div>

hr>

用于后台任务(与用户界面无关)



@UpTheCreek评论:


对于演示文稿问题很好,但仍然有
需要继续运行。


如果您有需要的后台任务按给定间隔精确执行,您可以使用 HTML5 Web Workers 。看看Möhre's answer below for more details ...



CSS vs JS动画



这个问题和其他许多可以通过使用CSS来避免转换/动画而不是基于JavaScript的动画,这增加了相当大的开销。我建议您使用 jQuery插件 ,让您从CSS转换中受益就像 animate()方法一样。


I have a setInterval running a piece of code 30 times a second. This works great, however when I select another tab (so that the tab with my code becomes inactive), the setInterval is set to an idle state for some reason.

I made this simplified test case (http://jsfiddle.net/7f6DX/3/):

var $div = $('div');
var a = 0;

setInterval(function() {
    a++;
    $div.css("left", a)
}, 1000 / 30);

If you run this code and then switch to another tab, wait a few seconds and go back, the animation continues at the point it was when you switched to the other tab. So the animation isn't running 30 times a second in case the tab is inactive. This can be confirmed by counting the amount of times the setInterval function is called each second - this will not be 30 but just 1 or 2 if the tab is inactive.

I guess that this is done by design so as to improve performance, but is there any way to disable this behaviour? It is actually a disadvantage in my scenario.

解决方案

On most browsers inactive tabs have low priority execution and this can affect JavaScript timers.

If the values of your transition were calculated using real time elapsed between frames instead fixed increments on each interval, you not only workaround this issue but also can achieve a smother animation by using requestAnimationFrame as it can get up to 60fps if the processor isn't very busy.

Here's a vanilla JavaScript example of an animated property transition using requestAnimationFrame:

var target = document.querySelector('div#target')
var startedAt, duration = 3000
var domain = [-100, window.innerWidth]
var range = domain[1] - domain[0]

function start() {
  startedAt = Date.now()
  updateTarget(0)
  requestAnimationFrame(update)
}

function update() {
  let elapsedTime = Date.now() - startedAt

  // playback is a value between 0 and 1
  // being 0 the start of the animation and 1 its end
  let playback = elapsedTime / duration

  updateTarget(playback)
  
  if (playback > 0 && playback < 1) {
  	// Queue the next frame
  	requestAnimationFrame(update)
  } else {
  	// Wait for a while and restart the animation
  	setTimeout(start, duration/10)
  }
}

function updateTarget(playback) {
  // Uncomment the line below to reverse the animation
  // playback = 1 - playback

  // Update the target properties based on the playback position
  let position = domain[0] + (playback * range)
  target.style.left = position + 'px'
  target.style.top = position + 'px'
  target.style.transform = 'scale(' + playback * 3 + ')'
}

start()

body {
  overflow: hidden;
}

div {
    position: absolute;
    white-space: nowrap;
}

<div id="target">...HERE WE GO</div>


For Background Tasks (non-UI related)

@UpTheCreek comment:

Fine for presentation issues, but still there are some things that you need to keep running.

If you have background tasks that needs to be precisely executed at given intervals, you can use HTML5 Web Workers. Take a look at Möhre's answer below for more details...

CSS vs JS "animations"

This problem and many others could be avoided by using CSS transitions/animations instead of JavaScript based animations which adds a considerable overhead. I'd recommend this jQuery plugin that let's you take benefit from CSS transitions just like the animate() methods.

这篇关于如何在Chrome中的选项卡处于非活动状态时使setInterval也起作用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆