fish
fish

Reputation: 39

setInterval() speeding/slowing function propagation after a few cycles

Using setInterval() and clearInterval() to cycle through a carousel of 4 images. On initial page load, the functions seem to work as expected. However, after a few cycles and hovers, focusing out of the page, the cycle starts speeding up between a couple of images and remains fine within the other. Sometimes, it starts skipping images all together in the cycle. At times it also autocorrects and starts working fine again. Here's what I have:

jQuery(document).ready(function($) {
var count = -1;
var maxCount = $('.hero-blocks .block').length;
var colors = new Array('yellow', 'blue', 'promo', 'purple');
var autopager, timer = false;
var desktop = false,
    mobile = false;


function carousel() {
    if(count < maxCount - 1) {
        count++;
    } else {
        count = 0;
    }

    $('.hero-blocks .block.active').removeClass('active');
    $('.hero-blocks .block.' + colors[count] + '').addClass('active');

};

function startAutopager() {
    autopager = window.setInterval(carousel, 4000);

    timer = true;
}

function stopAutopager() {
    window.clearInterval(autopager);
    $('.hero-blocks .block').removeClass('active');

    timer = false;
}

function triggerCarousel() {
    if (Modernizr.mq('only screen and (min-width: 1024px)')) {
        // This stuff stops the carousel if the user goes to a different tab
        if(!desktop) {
            startAutopager();
            window.addEventListener('focus', startAutopager);
            window.addEventListener('blur', stopAutopager);

            desktop = true;
            mobile = false;

            $('.hero-blocks .block').hover(function() {
                stopAutopager();
            }, function() {
                startAutopager();
            });
        }
    } else if(!mobile) {
        stopAutopager();

        mobile = true;
        desktop = false;
    }
}
triggerCarousel();

$(window).resize(function() {
    triggerCarousel();
});
});

Upvotes: 1

Views: 129

Answers (1)

pablochan
pablochan

Reputation: 5715

I think the problem here is that it's possible to call window.setInterval(carousel, 4000) multiple times, since it's triggered during a couple of different events, and the code doesn't check if it's already running.

I suggest checking the value of timer before calling setInterval

function startAutopager() {
    if (!timer) {
        autopager = window.setInterval(carousel, 4000);

        timer = true;
    }
}

function stopAutopager() {
    if (timer) {
        window.clearInterval(autopager);
        $('.hero-blocks .block').removeClass('active');

        timer = false;
    }
}

Another minor point - setInterval doesn't guarantee perfect timing, so it's still possible that carousel will be triggered with different intervals.

Upvotes: 1

Related Questions