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:
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