Ojo con los $timeout

Dentro del desarrollo con el framework AngularJS, nos encontramos con un servicio llamado $timeout.

Podríamos decir que este servicio hace las veces de temporizador, y cuando lo llamas le tienes que pasar como argumento la función que debe hacer, y en qué periodo de tiempo.

Algo así como:

var myvar = $timeout($scope.myfunction, 3000);
$scope.myfunction = function()
{
    // Mi código por aquí.
};

Vendría a ejecutar el contenido de la función cuando se cumplan 5 segundos desde que llamamos la función.

Podríamos hacer un temporizador que, por ejemplo, refresque una tabla, haciendo algo así:

$scope.myvar = $timeout($scope.myfunction, 3000);
$scope.myfunction = function()
{
// Mi código por aquí.
$scope.myvar = $timeout($scope.myfunction, 3000)
};

Y dado este código, cada vez que se ejecutara la función, volvería a poner otro $timeout para que se vuelva a ejecutar indefinidamente.

Si en algún momento queremos cancelar el $timeout, es suficiente hacer:

$timeout.cancel($scope.myvar);

Y aparentemente, estaría cancelado. Pero… ¿y si hemos ido a otra vista o, peor aún, hemos refrescado la página sin hacer $timeout.cancel(…)? Aparentemente nada, todo parece correcto, pero si seguimos en la misma pantalla, el $timeout cada 5 segundos que hemos definido sigue ejecutándose, y lo peor de todo, en paralelo con el que se acaba de lanzar en la actual instancia de la página. ¿Puede ser esto un problema? Si, porque si nuestra función de actualizar los datos de la tabla es un poco pesada, estaremos ejecutando esta tarea 2 veces! y esto se incrementará cada vez que refresquemos sin haber cancelado antes el $timeout.

La solución, como se puede leer en multitud de blogs (que ya me he tenido que patear porque he caído en el error anterior), es cancelar los $timeout en los eventos $destroy del controlador:

$scope.$on("$destroy",function( event )
{
$timeout.cancel($scope.myvar);
});

Y con esto deberíamos evitar que el $timeout se nos acumule cada vez que llamemos a nuestro controlador.

Para una explicación, seguramente más clara, de este problema, podéis visitar también el siguiente blog: http://www.bennadel.com/blog/2548-don-t-forget-to-cancel-timeout-timers-in-your-destroy-events-in-angularjs.htm