Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

setInterval not working properly on Chrome

I have a custom made slideshow object to perform the usual stuff the name indicates on a website. It all works well except when I switch tabs in Chrome and come back to the website tab. When that happens, the slideshow goes nuts and starts fading the images disregarding the setInterval interval given. Can't find anyhing related to this, so I'd like to at least know if it's a problem with the code or a software issue.

Here's the code (being used with jQuery) :

$(function() {

    // slideshow
    var slideshow = {
        id : false,
        current : 0,
        count : 0,
        interval : false,
        init : function(data) {
            if (!data)
                return false;

            $.each(data, $.proxy(
                function(index, value) {
                    this[index] = data[index];
                }, this)
            );

            this.count = this.images.length;

            for (x=1;x<=this.count;x++)
                $('#slider ul.nav').append('<li></li>');

            $('#slider ul.nav li').live('click', function()
            {
                slideshow.click(this);
            });

            $('#slider ul.nav li:eq(0)').addClass('on');
            $('#slider ul.nav').css('width', (15*this.count)+'px');

            return true;
        },
        start : function () {
            slideshow.id = setInterval(function() { slideshow.action(); }, slideshow.options.interval);
        },
        stop : function() {
            clearInterval(slideshow.id);
        },
        action : function() {
            slideshow.current < (slideshow.count-1) ? slideshow.current++ : slideshow.current = 0;

            $('#slider img').fadeOut('normal', function() {
                $('#slider img').attr('src', slideshow.images[slideshow.current].url);
                $('#slider ul.nav li').removeClass('on');
                $('#slider ul.nav li:eq('+slideshow.current+')').addClass('on');
                $('#slider div.title').html(slideshow.images[slideshow.current].title);
                $('#slider div.description').html(slideshow.images[slideshow.current].description);
                $('#slider a.more').attr('href', slideshow.images[slideshow.current].target);
            }).fadeIn('normal');

            return true;
        },
        click : function(o) {
            slideshow.stop();

            var index = $('#slider ul.nav li').index(o);
            slideshow.current = index;

            $('#slider img').fadeOut('normal', function() {
                $('#slider img').attr('src', slideshow.images[index].url);
                $('#slider ul.nav li').removeClass('on');
                $(o).addClass('on');
                $('#slider div.title').html(slideshow.images[index].title);
                $('#slider div.description').html(slideshow.images[index].description);
                $('#slider a.more').attr('href', slideshow.images[index].target);
            }).fadeIn('normal');

            slideshow.start();
            return true;
        },
    };

    slideshow.init(slider);
    slideshow.start();

});
like image 282
yoda Avatar asked Aug 05 '11 05:08

yoda


People also ask

Why is setInterval not accurate?

Why are setTimeout and setInterval not accurate? To answer this question, you need to understand that there is a mechanism called event loop in the JavaScript host environment (browser or Node. js). It is necessary for front-end developers to understand this mechanism.

Does setInterval run when tab is not active?

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.

What can I use instead of setInterval?

Nested setTimeout calls are a more flexible alternative to setInterval , allowing us to set the time between executions more precisely. Zero delay scheduling with setTimeout(func, 0) (the same as setTimeout(func) ) is used to schedule the call “as soon as possible, but after the current script is complete”.

How do you clean setInterval?

Answer: Use the clearInterval() Method The setInterval() method returns an interval ID which uniquely identifies the interval. You can pass this interval ID to the global clearInterval() method to cancel or stop setInterval() call.

How do I stop Chrome from messing with interval timer?

Lengthen the time of the setInterval so Chrome won't mess with it (you'd have to look up what that time is). Stop your interval timer when the page goes in the background (no need to run slides when it's not visible anyway) - then start it up again when the page comes to the foreground. Similar post here. Show activity on this post.

Why settimeinterval should not be used in JavaScript?

In case of time intensive synchronous operations, setTimeInterval may break the rhythm. Also, if any error occurs in setInterval code block, it will not stop execution but keeps on running faulty code. Not to mention they need a clearInterval function to stop it.

How does setInterval () work for inactive tabs?

For inactive tabs, they automatically throttle timers to run every 1 second, regardless of the original delay specified in the code. For example, if the code originally used setInterval () to run some code every 50 ms, once the application is moved to a background tab, the interval automatically becomes 1000 ms (1 second).

Why does setInterval reduce the speed of a tab?

Chrome (and apparently the latest versions of Firefox too) reduce the speed of setInterval when the tab is in the background to improve foreground performance. This probably matters the most when there are fast running timer-driven animations in background pages.


1 Answers

Chrome (and apparently the latest versions of Firefox too) reduce the speed of setInterval when the tab is in the background to improve foreground performance. This probably matters the most when there are fast running timer-driven animations in background pages. When the page comes back to the foreground, it "tries" to catch up and runs a bunch of setInterval calls much faster than they would normally run.

The work-arounds are:

  1. Lengthen the time of the setInterval so Chrome won't mess with it (you'd have to look up what that time is).
  2. Stop your interval timer when the page goes in the background (no need to run slides when it's not visible anyway) - then start it up again when the page comes to the foreground.
  3. Use repeated setTimeout instead of setInterval with some type of repeated setTimeout like this:

Code:

function nextSlide() {
    // show next slide now
    // set timer for the slide after this one
    setTimeout(function() {
        nextSlide();       // repeat
    }, xxx)
}

Similar post here.

like image 158
jfriend00 Avatar answered Oct 19 '22 22:10

jfriend00