2011-08-05 18 views
9

Tengo un objeto de presentación de diapositivas hecho a medida para realizar las cosas habituales que el nombre indica en un sitio web. Todo funciona bien, excepto cuando cambio las pestañas en Chrome y vuelvo a la pestaña del sitio web. Cuando eso sucede, la presentación de diapositivas se vuelve loca y comienza a desvanecerse las imágenes sin tener en cuenta el intervalo setInterval dado. No puedo encontrar nada relacionado con esto, así que al menos quiero saber si hay un problema con el código o un problema de software.setInterval no funciona correctamente en Chrome

Aquí está el código (que se utiliza con 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(); 

}); 

Respuesta

11

Estoy a favor de usar setTimeout() repetidamente sobre el uso de setInterval() - muchas cosas pueden salir mal con setInterval() y no sabe qué tan ocupado está el navegador y si el intervalo es realista.

Los navegadores no respetan exactamente el tiempo de espera o intervalo elegido. Esto es principalmente por seguridad; para evitar que una avalancha de eventos interfiera con la capacidad del navegador para funcionar normalmente. Chrome es mejor para respetar los temporizadores con más precisión, aunque todavía los ralentiza significativamente cuando una pestaña está en segundo plano (see this answer), por ejemplo.

Si configura un nuevo temporizador con setTimeout durante su llamada existente a slideshow.action(), entonces no obtendrá eventos haciendo cola cuando su navegador no pueda mantener el ritmo, pero seguirá funcionando bien y rápidamente cuando el navegador puede hacerlo

Aún podrá detener el temporizador usando la ID del temporizador, esa ID solo cambiará a menudo.

+0

Intentó 'setTimeout()' sin ningún éxito. El problema con las pestañas de Chrome todavía sucede incluso si digo al script que haga la diferencia de marcas de tiempo y ajuste el intervalo (usando 'console.log' podría ver que nunca cambia, lo que me hace creer que Chrome congela el proceso de pestañas o algo así) . – yoda

+1

Ver esta respuesta: http://stackoverflow.com/questions/6032429/chrome-timeouts-interval-suspended-in-background-tabs/6032591#6032591 – thomasrutter

+0

Eso es todo, gracias :) – yoda

2

Lo más probable es que no debe esperar a setInterval sea siempre exacta. Si yo fuera usted, verificaría que el intervalo sea correcto comparando el tiempo de intervalo anterior con el intervalo actual. Eso debería hacer que el código sea más robusto.

8

Chrome (y al parecer las últimas versiones de Firefox también) reducen la velocidad de setInterval cuando la pestaña está en segundo plano para mejorar el rendimiento en primer plano. Esto probablemente es más importante cuando hay animaciones rápidas basadas en el temporizador en las páginas de fondo. Cuando la página vuelve al primer plano, "intenta" ponerse al día y ejecuta un montón de llamadas setInterval mucho más rápido de lo que normalmente se ejecutarían.

Las soluciones temporales son:

  1. alargar el tiempo de la setInterval tan Chrome no ensuciará con ella (que tendría que buscar lo que el tiempo es).
  2. Detenga el temporizador de intervalo cuando la página se ponga en segundo plano (no es necesario ejecutar las diapositivas cuando no esté visible de todos modos); luego vuelva a iniciarla cuando la página pase a primer plano.
  3. uso repetido setTimeout en lugar de setInterval con algún tipo de setTimeout repetida de esta manera:

Código:

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

puesto similar here.

+0

Interesante .... – karim79

+2

No funcionó. Chrome todavía se comporta como un niño. – yoda

0

Hubo un problema similar con cromo

Como he resuelto este problema. Al comienzo, anote la variable mktime, y luego restarla de la hora actual.Ejemplo:

var values = {}; 

function mktime(){ 
var date = new Date(); 
return Math.floor(date.getTime()/1000); 
} 
function getTime(string){ 
    var splitContent = string.split(/\:/g); 
    var hours = parseInt(splitContent[0]) * 60 * 60; 
    var minutes = parseInt(splitContent[1]) * 60; 
    var seconds = parseInt(splitContent[2]);       
    return hours + minutes + seconds; 
} 
function startTimer(time){ 

values.startMkTime = mktime(); 
values.startTime = getTime(time); 
setInterval(process(),1000);      
} 

function process(){ 
    values.currentTime = (mktime() - values.startMkTime) +  o.values.startTime;//new code 
} 
+0

'setInterval (process(), ...) 'intentará ejecutar el valor de retorno de' process', que seguramente no es lo que quieres. 'setInterval' toma una referencia de función como su primer argumento (o una cadena, pero no es importante aquí). –

Cuestiones relacionadas