sábado, 2 de abril de 2011

Javascript: Usar métodos de clases con setInterval y setTimeout

El objeto Window de Javascript posee dos métodos que nos permiten lanzar una acción luego de cierto tiempo:



  • setTimeout lanza la acción una vez luego del tiempo especificado

  • setInterval lanza la acción en intervalos regulares de duración especificada


Por ejemplo:



<script type="text/javascript">
setTimeout('alert("Hola mundo")'. 5000); // Muestra la alerta hola mundo luego de 5000 milisegundos (5 segundos)
setTimeout('alert("Hola mundo")'. 3000); // Muestra la alerta hola mundo cada 3000 milisegundos (3 segundos)
</script>


Pero un problema clásico que sucede cuando trabajamos con clases en Javascript es podemos querer usar setInterval o setTimeout en un método de nuestra clase que ejecute como acción un llamado a un método de su misma instancia. Una primera solución que se nos ocurriría podría ser esta:


<script type="text/javascript">
function MiClase()
{
this.miIntervalo = null;
}

MiClase.prototype.miMetodo = function()
{
alert("Hola Mundo");
}

MiClase.prototype.iniciarIntervalo = function()
{
this.intervalo = setInterval('this.miMetodo()', 3000); // Esto no funcionará: utilizo 'this' (local) en el global scope
}

var miInstancia = new MiClase();
miInstancia.iniciarIntervalo();
</script>


Sin embargo el código anterior no funcionará, generando un error.


¿Por qué?

Como setTimeout y setInterval son métodos de la clase window, ejecutan sus acciones en el scope global, pero 'this' no pertenece al scope global, sino que es local a la instancia de la clase. Al tratar de ejecutar la acción setInterval no encontrará el objeto llamado this y devolverá un error.




Una solución


Una forma de solucionar esto es mantener una colección de objetos por fuera de la clase y asignar a cada instancia una key, en el constructor hacemos que el objeto se guarde a sí mismo en la colección y luego, cuando le indiquemos a setInterval o setTimeout cuál es la acción a ejecutar, utilizamos la colección en lugar de 'this'



Ejemplo de la solución



<script type="text/javascript">
var objetosMiClase = new Object(); // Mi colección de instancias de MiClase

function MiClase()
{
this.miIntervalo = null;
var date = new Date();
this.key = date.getTime() + date.getMilliseconds(); // Genero una key, se pueden usar otras técnicas
objetosMiClase[this.key] = this; // La instancia se guarda a sí misma en la colección
}

MiClase.prototype.miMetodo = function()
{
alert("Hola Mundo");
}

MiClase.prototype.iniciarIntervalo = function()
{
this.intervalo = setInterval('objetosMiClase[' + this.key + '].miMetodo()', 3000); // Funciona! utilizo un objeto del global scope en lugar de 'this'
}

var miInstancia = new MiClase();
miInstancia.iniciarIntervalo();
</script>


Esta es una solución rápida al problema de intentar llamar un objeto de la misma instancia utilizanso setInterval o setTimeout

1 Comentário:

Tury dijo...

Muy bueno!
Sí, funciona muy bien.

Igual, es una lástima igual que en Javascript se tenga que recurrir a este tipo de técnicas para realizar algo que debería ser más sencillo.

Muchas gracias
Saludos

Publicar un comentario

Epistemomaniáticos ©Template Blogger Green by Dicas Blogger.

TOPO