问题
I've written a simple Slider in jQuery with autplay. If autoplay is enabled a setTimeout is set that points to a function. This function then has a recursive setTimeout to itself.
All works well, except in Chrome. After I've changed a tab, wait for a while and return, the slider is freaking out. It looks like there are multiple instances of the timeout active... but that cannot be the case since I appoint the timeout to the same variable.
Some relevant code:
var timer;
function autoplay() {
currentPosition++;
if(currentPosition == numberOfSlides) {
// last slide
currentPosition = 0;
}
manageNavigation(currentPosition);
// Hide / show controls
manageControls(currentPosition);
// animate the slides
slideshowAnimate();
// set timer
if(autoplay_enable) {
//clearTimeout(timer);
timer = setTimeout(function() { autoplay() }, interval*1000)
}
}
function setTimer() {
if(autoplay_enable) {
timer = setTimeout(function() { autoplay() }, interval*1000)
}
}
setTimer();
回答1:
No, resetting the value of timer
will not cancel the current timer. For that you need to clearTimeout
. All timer holds is a numeric reference to the timer, not a closure or anything of that nature.
Assuming you have a good condition to start setTimer()
, your code should look more like this:
var timer;
function autoplay() {
clearTimeout(timer); //! New code.
currentPosition++;
if(currentPosition == numberOfSlides) {
// last slide
currentPosition = 0;
}
manageNavigation(currentPosition);
// Hide / show controls
manageControls(currentPosition);
// animate the slides
slideshowAnimate();
// set timer
setTimer(); //! Switched from having multiple startup locations.
}
function setTimer() {
if(autoplay_enable) {
timer = setTimeout(autoplay, interval*1000); //! Removed unnecessary closure.
}
}
setTimer();
回答2:
the return of the setTimeout is an index number that is used for internal recognition of the timers, not the actual timer itself. therefore you are only writing over the thing that is pointing to a timer, not removing the timer that is running when you make the timer again.
To save computing power, the chrome engine freezes most javascript running in background tabs, and then seems to try and "catch up" when it gets back in focus. Not sure what the fix would be for this though. definitely use the clearTimeout or better yet use a Timer object to try and catch this as a repetetive action.
回答3:
I've tried found a small fix. You can try to add this to your code
var timer;
...
$(window).blur(function() {
clearTimeout(timer);
}).focus(function() {
timer= setInterval(autoplay, interval*1000);
});
Hope this can help.
来源:https://stackoverflow.com/questions/7064237/chrome-timeout-problem-with-animation