setInterval error en Chrome y Firefox

Hace unos días encontré un error en una animación que hice en jQuery, que hace uso de setInterval.  SetInterval existe para ejecutar una función cada determinada cantidad de tiempo. Supongamos que estoy en un sitio que hace uso de esta función, pero después voy a otro tab del browser, y me quedo navegando allí durante unos minutos, eso quiere decir que en otro tab (que no estoy viendo…) se debería estar ejecutando una función.

Firefox y Chrome evitan que las funciones con setInterval se ejecuten si uno está viendo otro tab. Tiene sentido, intentan ahorrar memoria para ponerla, justamente, donde el usuario esté mirando. El único problema es que en vez de hacer un «pause», lo que hacen es ir guardando todas las veces que se deberían ejecutar. Lo que provoca que cuando finalmente volvemos a hacer foco, se ejecutan una detrás de la otra!

La solución es increiblemente fácil cuando las funciones con setInterval involucran animaciones, como en mi caso.

Primero les muestro el código sin la corrección:

function magic(elemento){
	$(elemento).animate({
		left: '-=1',
		bottom: '+=2'
	}, 70, function() {
		// Animation complete.
		$(this).animate({
		left: '+=3'
		}, 70, function(){
			$(this).animate({
				left:'-=2',
				bottom:'-=2'
			}, 70)
		});
	});
}

Este código lo que hace es mover un div hacia la izquierda y abajo, y luego hacia la posición original, provocando un ligero temblor. Para ejecutarlo, uso por ejemplo:

setInterval("magic('.banner')",5000);

Lo que hace que cada 5 segundos, el div banner tiemble. Al perder el foco y luego volver al tab, la ejecuciòn en cadena hacia que el banner se fuera no 1, sino por ejemplo 200 pixeles hacia la izquierda (y hacia abajo…). Quedaba horrible por el hecho de quedar en cola de ejecución la función de temblor.

La solución es borrar lo que haya en memoria:

function magic(elemento){
	$(elemento).stop(true,true).animate({
		left: '-=1',
		bottom: '+=2'
	}, 70, function() {
		// Animation complete.
		$(this).animate({
		left: '+=3'
		}, 70, function(){
			$(this).animate({
				left:'-=2',
				bottom:'-=2'
			}, 70)
		});
	});
}

Así de simple…

Últimas entradas de turu (ver todo)