最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - setTimeout speeds up with multiple tabs - Stack Overflow

programmeradmin1浏览0评论

I’m having a setTimeout problem similar to this one. But that solution doesn't help me since I can’t use php in my file.

My site has a slider with a list of images that move every 8 seconds.However, when I have opened a few tabs in the browser and then switch back again, it goes nuts. The slider proceeds to move the images one after the other immediately without the 8 second timedelay.

I'm only seeing it in Chrome and the latest Firefox.

**EDIT: I checked with console.log() and the setTimeout returns the same number before and after the clearTimeout. Not sure why. Maybe that also has something to do with it? **

EDIT 2: I added a fiddle: /

The code looks something like:

spotlight: {
    i: 0,
   timeOutSpotlight: null,

   init: function()
   {
       $('#spotlight .controls a').click(function(e) {

           // do stuff here to count and move images

           // Don't follow the link
           e.preventDefault();

           // Clear timeout
           clearTimeout(spotlight.timeOutSpotlight);

           // Some stuff here to calculate next item

           // Call next spotlight in 8 seconds
           spotlight.timeOutSpotlight = setTimeout(function () {
                spotlight.animate(spotlight.i);
            }, 8000);
       });

       // Select first item
       $('#spotlight .controls a.next:first').trigger('click');
   },

   animate: function(i)
   {
       $('#spotlight .controls li:eq(' + (spotlight.i) + ') a.next').trigger('click');
   }
}

I’m having a setTimeout problem similar to this one. But that solution doesn't help me since I can’t use php in my file.

My site has a slider with a list of images that move every 8 seconds.However, when I have opened a few tabs in the browser and then switch back again, it goes nuts. The slider proceeds to move the images one after the other immediately without the 8 second timedelay.

I'm only seeing it in Chrome and the latest Firefox.

**EDIT: I checked with console.log() and the setTimeout returns the same number before and after the clearTimeout. Not sure why. Maybe that also has something to do with it? **

EDIT 2: I added a fiddle: http://jsfiddle.net/Rembrand/qHGAq/8/

The code looks something like:

spotlight: {
    i: 0,
   timeOutSpotlight: null,

   init: function()
   {
       $('#spotlight .controls a').click(function(e) {

           // do stuff here to count and move images

           // Don't follow the link
           e.preventDefault();

           // Clear timeout
           clearTimeout(spotlight.timeOutSpotlight);

           // Some stuff here to calculate next item

           // Call next spotlight in 8 seconds
           spotlight.timeOutSpotlight = setTimeout(function () {
                spotlight.animate(spotlight.i);
            }, 8000);
       });

       // Select first item
       $('#spotlight .controls a.next:first').trigger('click');
   },

   animate: function(i)
   {
       $('#spotlight .controls li:eq(' + (spotlight.i) + ') a.next').trigger('click');
   }
}
Share Improve this question edited May 23, 2017 at 12:00 CommunityBot 11 silver badge asked May 24, 2011 at 15:10 RembrandRembrand 4073 silver badges13 bronze badges 5
  • 1 Does this only happen if you open new tabs of your same site, or if you open any new tabs and switch back? – namuol Commented May 24, 2011 at 15:29
  • Just random tabs of any site. – Rembrand Commented May 24, 2011 at 15:47
  • How intriguing. Some additional tests to help see what is going on - during the callback, if you console.log the datetime to see the real interval at which the code is hitting - is it 8 seconds? And, if you leave the page for X # of seconds, do you see the correct # of console logging events for the elapsed time given? – Matt Commented May 24, 2011 at 16:05
  • If you continue to struggle with this, I'd suggest replicating it with jsfiddle.net and posting the fiddle here. – namuol Commented May 24, 2011 at 18:28
  • Fiddle added: jsfiddle.net/Rembrand/qHGAq/3 – Rembrand Commented May 25, 2011 at 6:52
Add a comment  | 

7 Answers 7

Reset to default 13

From the jQuery documentation:

Because of the nature of requestAnimationFrame(), you should never queue animations using a setInterval or setTimeout loop. In order to preserve CPU resources, browsers that support requestAnimationFrame will not update animations when the window/tab is not displayed. If you continue to queue animations via setInterval or setTimeout while animation is paused, all of the queued animations will begin playing when the window/tab regains focus. To avoid this potential problem, use the callback of your last animation in the loop, or append a function to the elements .queue() to set the timeout to start the next animation.

I finally found my answer and it’s not at all what I was expecting. It seems the culprit is jQuery’s .animate(), which I use to move the images in the slider.

I calculate and move my images positions with this:

$('.spotlight-inner')
    .animate(
        { left: scrollToVal },
        {duration: 'slow'}
    )
 ;

Now the problem seems to be that in some browsers, after you switch to a new tab and back, jQuery’s .animate() saves up the animations and fires them all at once. So I added a filter to prevent queueing. That solutions comes from CSS-Tricks.com :

$('.spotlight-inner')
    .filter(':not(:animated)')
    .animate(
        { left: scrollToVal },
        {duration: 'slow'}
    )
;

The first slide you see when you go back can act a little jumpy but it’s better than the superspeed carousel from before.

Fiddle with the full code here

There is an easier way using the jquery animate queue property:

$(this).animate({
    left: '+=100'
}, {duration:500, queue:false});

I don't know if this will help you, but it helped me with my slideshow. What I did was everytime I called an animation that was supposed to happen at a set interval because of the setTimeout, I called clearQueue() which would get rid of any other animations that had been set to happen. then i'd call the animation. That way when you come back to that tab, you don't have all these animations queued up and it goes crazy. at max you'll only have one set up.

So something like this:

       spotlight.timeOutSpotlight = setTimeout(function () {
            spotlight.clearQueue(); // get rid of other instances of the animation
            spotlight.animate(spotlight.i);
        }, 8000);

It may not work in all cases (depending on timing), but I hope that helps somebody!

You must also think you use clearTimeout.

As you call setTimeout function it returns an ID you can save this ID in a variable like

timeoutID = setTimeout(function () {
                spotlight.animate(spotlight.i);
            }, 8000);

and before setting a new timeout you can call the function like

clearTimeout(timeoutID)

My suspicion is that the browser queues input events like 'click' but only fires them when the tab where the event occurs actually has focus.

Perhaps you should try calling your click callbacks directly instead of using trigger('click').

Something like this:

spotlight: {
    i: 0,
   timeOutSpotlight: null,
   clickFunc: function(element) {

       // do stuff here to count and move images

       // Clear timeout
       clearTimeout(spotlight.timeOutSpotlight);

       // Some stuff here to calculate next item

       // Call next spotlight in 8 seconds
       spotlight.timeOutSpotlight = setTimeout(function () {
            spotlight.animate(spotlight.i);
       }, 8000);
   },

   init: function()
   {

       $('#spotlight .controls a').click(function (e) {

           // Don't follow the link
           e.preventDefault();

           spotlight.clickFunc(this);
       });

       // Select first item
       spotlight.clickFunc($('#spotlight .controls a.next:first'));
   },

   animate: function(i)
   {
       var element = $('#spotlight .controls li:eq('+spotlight.i+') a.next');
       spotlight.clickFunc(element);
   }
}

What version of jQuery are you running? Apparently this problem was 'fixed' for version 1.6.3 - they reverted the change that caused this to happen. Discussions here and here.

Though this issue will likely have to be addressed in the future, it seems as though we're off the hook for now.

发布评论

评论列表(0)

  1. 暂无评论