2010-09-02 4 views
15

Je veux le faire soit par javascript pur ou n'importe quel type de console dans un navigateur ou autre.Comment puis-je afficher une liste de tous les threads générés par setTimeout/setInterval

Est-ce possible?

Merci

Des explications complémentaires: Je veux déboguer une bibliothèque qui fait des animations. Je veux savoir s'il y a plusieurs minuteurs créés si plusieurs objets sont animés.

+0

Mike, pouvez-vous s'il vous plaît s'il vous plaît ajouter plus de détails? –

+1

voulez-vous juste une liste d'ID de délai d'attente en cours d'exécution? javascript n'utilise pas de threads ... – brad

Répondre

6

Comme d'autres l'ont mentionné, setTimeout ne génère pas de thread. Si vous voulez une liste de tous les temps mort ids (afin que vous puissiez les annuler, par exemple), puis voir ci-dessous:


Je ne pense pas que vous pouvez obtenir une liste de tous les ids délai d'attente sans changer le code lorsque elles sont appelées. setTimeout renvoie un ID-et si vous l'ignorez, il est inaccessible à votre JavaScript. (Il est évident que l'interprète a accès, mais votre code ne fonctionne pas.)

Si vous pouviez changer le code que vous pouvez faire:

var timeoutId = []; 

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

... Faire en sorte que timeoutId est déclarée dans une portée globale (peut-être en utilisant window.timeoutId = []).


Situé juste à côté du haut de ma tête, mais réimplémenter setTimeout vous auriez à faire quelque chose comme ceci:

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

Ce n'est pas testé, mais il vous donne un point de départ. Bonne idée, molf!

Edit:aularon's answer donne une mise en œuvre beaucoup plus approfondie de l'idée ci-dessus.

+3

Vous pouvez redéfinir 'setTimeout()' pour stocker les identifiants dans un tableau quelque part. De cette façon, aucun code ne doit être modifié, il suffit d'injecter du Javascript avant de l'exécuter. – molf

+0

@molf, comment faites-vous cela? –

+0

@molf bon point. – Skilldrick

10

Notez que setTimeout() ne génère pas de nouveaux threads. Les scripts côté navigateur ne sont pas seulement à un seul thread, mais l'évaluation JavaScript partage le même thread unique avec le rendu de la page (Web Workers séparément).

Pour en savoir plus:

Vous pouvez créer un gestionnaire de minuterie vous:

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; 
     } 
    }; 
})(); 

utiliser ensuite comme suit:

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); 

ci-dessus affichera le résultat suivant dans la console:

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

Notez que la mise en œuvre timerManager ci-dessus utilise la méthode Array.indexOf(). Ceci a été ajouté dans JavaScript 1.6 et donc pas implémenté par tous les navigateurs. Cependant, vous pouvez facilement ajouter la méthode vous-même en ajoutant l'implémentation de this Mozilla Dev Center article.

+0

Merci d'y jeter un coup d'œil –

+0

L'article de John Resig est très utile, probablement la meilleure explication des événements asynchrones à un seul thread que j'ai rencontrés jusqu'à présent. Merci aussi pour l'excellent code. – Bob

8

Enfin fait, il était intéressant pour moi, donc j'ai passé quelque temps à essayer de trouver quelque chose, et here it's

Elle remplace le statut actif de setTimeout et remplir le navigateur d'appels actifs en cours dans window._activeSetTimeouts hachage, avec window._showCurrentSetTimeouts() fonction de démonstration qui affiche les appels setTimeout en cours d'attente.

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

Très bien, chapeaux à vous! – Skilldrick

+0

un peu en retard mais merci pour cette réponse, très utile. Cependant, j'ai dû changer l'appel 'cb();' dans la 4ème ligne de 'window.setTimeout': l'argument soumis dans setTimeout peut être une fonction ou la représentation sous forme de chaîne d'un code javascript. – BiAiB

+0

* clap * ... * clap * ... * clap * .. * clap * * clap * * clap * * clap * * applaudissements *. Incroyable. Merci beaucoup d'avoir partagé! – Mike

Questions connexes