ejemplos - javascript html
¿Cómo manejas múltiples instancias de setTimeout()? (9)
¿Cuál es la forma más recomendada / mejor para evitar que se creen varias instancias de una función setTimeout (en javascript)?
Un ejemplo (código de psuedo):
function mouseClick()
{
moveDiv("div_0001", mouseX, mouseY);
}
function moveDiv(objID, destX, destY)
{
//some code that moves the div closer to destination
...
...
...
setTimeout("moveDiv(objID, destX, destY)", 1000);
...
...
...
}
Mi problema es que si el usuario hace clic varias veces en el mouse, tengo varias instancias de moveDiv () que se llama.
La opción que he visto es crear una bandera, que solo permita que se llame al tiempo de espera si no hay otra instancia disponible ... ¿es la mejor manera de hacerlo?
Espero que eso lo aclare ...
Puede almacenar múltiples banderas en una tabla de búsqueda (hash) usando objID
como clave.
var moving = {};
function mouseClick()
{
var objID = "div_0001";
if (!moving[objID])
{
moving[objID] = true;
moveDiv("div_0001", mouseX, mouseY);
}
}
Puede establecer un indicador global en alguna parte (como var mouseMoveActive = false;) que le indica si ya está en una llamada y, de ser así, no inicia la siguiente. Establece el indicador justo antes de ingresar a la llamada a setTimeout, después de verificar si ya está configurado. Luego, al final de la rutina llamada en setTimeout () puede restablecer el indicador.
siempre puede sobrescribir los botones al hacer clic para devolver falso. ejemplo:
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="UTF-8">
<head>
<title>Javascript example</title>
<script type="text/javascript">
var count = 0;
function annoy() {
document.getElementById(''testa'').onclick = function() { return false; };
setTimeout(function() {
alert(''isn/'t this annoying? '' + count++);
document.getElementById(''testa'').onclick = window.annoy;
}, 1000);
}
</script>
</head>
<body>
<h2>Javascript example</h2>
<a href="#" onClick="annoy()" id="testa">Should Only Fire Once</a><br />
</body>
</html>
var timeout1 = window.setTimeout(''doSomething();'', 1000);
var timeout2 = window.setTimeout(''doSomething();'', 1000);
var timeout3 = window.setTimeout(''doSomething();'', 1000);
// to cancel:
window.clearTimeout(timeout1);
window.clearTimeout(timeout2);
window.clearTimeout(timeout3);
No he probado nada de esto y simplemente lo corté en el editor aquí. Podría funcionar, quizás no, con suerte será algo para pensar.
var Timeout = {
_timeouts: {},
set: function(name, func, time){
this.clear(name);
this._timeouts[name] = {pending: true, func: func};
var tobj = this._timeouts[name];
tobj.timeout = setTimeout(function()
{
/* setTimeout normally passes an accuracy report on some browsers, this just forwards that. */
tobj.func.call(arguments);
tobj.pending = false;
}, time);
},
hasRun: function(name)
{
if( this._timeouts[name] )
{
return !this._timeouts[name].pending;
}
return -1; /* Whut? */
},
runNow: function(name)
{
if( this._timeouts[name] && this.hasRun(name)===false )
{
this._timeouts[name].func(-1); /* fake time. *shrug* */
this.clear(name);
}
}
clear: function(name)
{
if( this._timeouts[name] && this._timeouts[name].pending )
{
clearTimeout(this._timeouts[name].timeout);
this._timeouts[name].pending = false;
}
}
};
Timeout.set("doom1", function(){
if( Timeout.hasRun("doom2") === true )
{
alert("OMG, it has teh run");
}
}, 2000 );
Timeout.set("doom2", function(){
/* NooP! */
}, 1000 );
Las llamadas sucesivas con el mismo identificador cancelarán la llamada anterior.
Puede evitar una variable global o menor al usar una propiedad dentro de la función. Esto funciona bien si la función solo se usa para este contexto específico.
function set_time_out( id, code, time ) /// wrapper
{
if(typeof this.timeout_handles == ''undefined'') this.timeout_handles = [];
if( id in this.timeout_handles )
{
clearTimeout( this.timeout_handles[id] )
}
this.timeout_handles[id] = setTimeout( code, time )
}
cuando llamas a settimeout, te devuelve una variable "manejar" (un número, creo)
si llama a settimeout por segunda vez, primero debe
clearTimeout( handle )
entonces:
handle = setTimeout( ... )
para ayudar a automatizar esto, puede usar un contenedor que asocie llamadas de tiempo de espera con una cadena (es decir, el id del div o cualquier cosa que desee), de modo que si hay un settimeout anterior con la misma "cadena", lo borra automáticamente antes poniéndolo de nuevo,
Utilizaría una matriz (es decir, diccionario / hashmap) para asociar cadenas con identificadores.
var timeout_handles = []
function set_time_out( id, code, time ) /// wrapper
{
if( id in timeout_handles )
{
clearTimeout( timeout_handles[id] )
}
timeout_handles[id] = setTimeout( code, time )
}
Por supuesto, hay otras formas de hacerlo ...
Estoy usando esto para forzar una recolección de basura en todas las referencias de tiempo de espera obsoletos que realmente no modificaron la preforma de mi script:
var TopObjList = new Array();
function ColorCycle( theId, theIndex, RefPoint ) {
...
...
...
TopObjList.push(setTimeout( function() { ColorCycle( theId, theIndex ,CCr ); },CC_speed));
TO_l = TopObjList.length;
if (TO_l > 8888) {
for (CCl=4777; CCl<TO_l; CCl++) {
clearTimeout(TopObjList.shift());
}
}
}
Mi código descuidado original estaba generando una matriz masiva de más de 100.000 de profundidad en muy poco tiempo, pero esto realmente funcionó.
Lo haría de esta manera:
// declare an array for all the timeOuts
var timeOuts = new Array();
// then instead of a normal timeOut call do this
timeOuts["uniqueId"] = setTimeout(''whateverYouDo("fooValue")'', 1000);
// to clear them all, just call this
function clearTimeouts() {
for (key in timeOuts) {
clearTimeout(timeOuts[key]);
}
}
// clear just one of the timeOuts this way
clearTimeout(timeOuts["uniqueId"]);