2010-09-02 12 views
15

Quiero hacer esto por javascript puro o cualquier tipo de consola en un navegador o lo que sea.¿Cómo puedo mostrar una lista de cada subproceso en ejecución generado por setTimeout/setInterval

¿Es posible?

Gracias

Más explicaciones: que quieren depurar una biblioteca que hace animaciones. Quiero saber si hay múltiples temporizadores creados si hay varios objetos animados.

+0

Mike, por favor, ¿puede agregar más detalles? –

+1

¿desea que solo se ejecute una lista de id de tiempo de espera? javascript no usa hilos ... – brad

Respuesta

6

Como han mencionado otros, setTimeout no genera un hilo. Si desea una lista de todos los identificadores de tiempo de espera (por lo que puede cancelarlos, por ejemplo), entonces ver a continuación:


no creo que se puede obtener una lista de todos los identificadores de tiempo de espera sin cambiar el código cuando se se les llama. setTimeout devuelve una identificación, y si la ignora, no puede acceder a su JavaScript. (Obviamente, el intérprete tiene acceso a ella, pero el código no lo hace.)

Si pudiera cambiar el código que podría hacer esto:

var timeoutId = []; 

timeoutId.push(setTimeout(myfunc, 100)); 

... Asegurarse de que timeoutId se declara en el ámbito global (quizás usando window.timeoutId = []).


Justo al lado de la parte superior de la cabeza, pero volver a implementar setTimeout que tendría que hacer algo como esto:

var oldSetTimeout = setTimeout; 
setTimeout = function (func, delay) { 
    timeoutId.push(oldSetTimeout(func, delay)); 
} 

Esto no se ha probado, pero le da un punto de partida. Buena idea, señor!

Editar:aularon's answer ofrece una implementación mucho más completa de la idea anterior.

+3

En realidad podría redefinir 'setTimeout()' para almacenar los identificadores en una matriz en alguna parte. De esta forma, no es necesario modificar ningún código, solo tiene que insertar Javascript antes de que se ejecute. – molf

+0

@molf, ¿cómo haces esto? –

+0

@molf buen punto. – Skilldrick

10

Tenga en cuenta que setTimeout() no genera nuevos subprocesos. Las secuencias de comandos del lado del navegador no son solo de un solo subproceso, sino que la evaluación de JavaScript comparte el mismo subproceso con la representación de página (Web Workers aparte).

Más información:

Es posible que desee construir un gestor de temporizador de sí mismo:

var timerManager = (function() { 
    var timers = []; 
    return { 
     addTimer: function (callback, timeout) { 
     var timer, that = this; 
     timer = setTimeout(function() { 
      that.removeTimer(timer); 
      callback(); 
     }, timeout); 
     timers.push(timer); 
     return timer; 
     }, 
     removeTimer: function (timer) { 
     clearTimeout(timer); 
     timers.splice(timers.indexOf(timer), 1); 
     }, 
     getTimers: function() { 
     return timers; 
     } 
    }; 
})(); 

A continuación, utilice la siguiente manera:

var t1 = timerManager.addTimer(function() { 
    console.log('Timer t1 triggered after 1 second'); 
}, 1000); 

var t2 = timerManager.addTimer(function() { 
    console.log('Timer t2 triggered after 5 second'); 
    console.log('Number of Timers at End: ' + timerManager.getTimers().length); 
}, 5000); 

console.log('Number of Timers at Start: ' + timerManager.getTimers().length); 

Lo anterior se mostrará el siguiente resultado en la consola:

// Number of Timers at Start: 2 
// Timer t1 triggered after 1 second 
// Timer t2 triggered after 5 second 
// Number of Timers at End: 0 

Tenga en cuenta que la aplicación timerManager anterior utiliza el método Array.indexOf(). Esto ha sido agregado en JavaScript 1.6 y, por lo tanto, no implementado por todos los navegadores. Sin embargo, puede agregar el método fácilmente agregando la implementación desde this Mozilla Dev Center article.

+0

Gracias, echaré un vistazo a eso –

+0

El artículo de John Resig es muy útil, probablemente la mejor explicación de los eventos asíncronos de un solo hilo que he encontrado hasta ahora. Gracias también por el excelente código. – Bob

8

último hecho, fue interesante para mí, así que pasé algún tiempo tratando de llegar a algo, y here it's

anula el navegador del setTimeout y rellenar estado activo de llamadas activas actuales en window._activeSetTimeouts hachís, con window._showCurrentSetTimeouts() función de demostración que muestra las llamadas actuales setTimeout que están esperando.

if(typeof window._setTimeout =='undefined') { 
window._setTimeout=window.setTimeout; 

window._activeSetTimeouts={}; 
window._activeSetTimeoutsTotal=0; 
window._setTimeoutCounter=0; 
window._showCurrentSetTimeouts=function() { 
    var tgt=document.getElementById('_settimtouts'); 
    if(!tgt) { 
    tgt=document.createElement('UL'); 
    tgt.style.position='absolute'; 
    tgt.style.border='1px solid #999'; 
    tgt.style.background='#EEE'; 
    tgt.style.width='90%'; 
    tgt.style.height='500px'; 
    tgt.style.overflow='auto'; 
    tgt.id='_settimtouts'; 

    document.body.appendChild(tgt); 
    } 

    tgt.innerHTML=''; 
    var counter=0; 
    for(var i in window._activeSetTimeouts) { 
     var li=document.createElement('LI'); 
     li.innerHTML='[{status}] {delay} ({calltime})<br /><pre style="width: 100%; height: 5em; overflow: auto; background: {bgcolor}">{cb}</pre>'.f(window._activeSetTimeouts[i]); 
     li.style.background=(counter++%2)?'#CCC' : '#EEB'; 
     tgt.appendChild(li); 
    } 
} 
window.setTimeout=function(cb, delay) { 
    var id = window._setTimeoutCounter++; 
    var handleId = window._setTimeout(function() { 
    window._activeSetTimeouts[id].status='exec'; 
    cb(); 
    delete window._activeSetTimeouts[id]; 
    window._activeSetTimeoutsTotal--; 
    }, delay); 

    window._activeSetTimeouts[id]={ 
    calltime:new Date(), 
    delay:delay, 
    cb:cb, 
    status:'wait' 
    }; 
    window._activeSetTimeoutsTotal++; 
    return id; 
} 

//the following function is for easy formatting 

String.prototype.f=function(obj) { 
var newStr=this+''; 
if(arguments.length==1) { 
if(typeof(obj)=='string') { 
    obj={x:obj}; 
} 


for(var i in obj) { 
    newStr=newStr.replace(new RegExp('{'+i+'}', 'g'), obj[i]+''); 
} 
newStr+=''; 

} else { 
    for(var i=0; i<arguments.length; i++) { 
    newStr=newStr.replace('{'+(i+1)+'}', arguments[i]); 
    } 
} 
return newStr; 
} 
} 

//following line for test 
for(var i=0; i<5; i++) setTimeout(window._showCurrentSetTimeouts, 3000*i); 
+1

¡Muy bien, felicitaciones a usted! – Skilldrick

+0

un poco tarde, pero gracias por esa respuesta, muy útil. Sin embargo, tuve que cambiar la llamada 'cb();' en la cuarta línea de 'window.setTimeout': el argumento enviado en setTimeout puede ser una función o la representación de cadena de algún código javascript. – BiAiB

+0

* aplaudir * ... * aplaudir * ... * aplaudir * .. * aplaudir * * aplaudir * * aplaudir * * aplaudir * * aplausos *. Asombroso. ¡Muchas gracias por compartir! – Mike

Cuestiones relacionadas