Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I show a list of every thread running spawned by setTimeout/setInterval

I want to do this either by pure javascript or any sort of console in a browser or whatever.

Is it possible?

Thanks

Further explanations: I want to debug a library that does animations. I want to know if there's multiple timers created if there are multiple objects being animated.

like image 527
Mike Gleason jr Couturier Avatar asked Sep 02 '10 13:09

Mike Gleason jr Couturier


2 Answers

Note that setTimeout() does not spawn new threads. Browser side scripting is not only single threaded, but the JavaScript evaluation shares the same single thread with the page rendering (Web Workers apart).

Further reading:

  • How JavaScript Timers Work by John Resig

You may want to build a timer manager yourself:

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

Then use it as follows:

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

The above will display the following result in the 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

Note that the timerManager implementation above uses the Array.indexOf() method. This has been added in JavaScript 1.6 and therefore not implemented by all browsers. However, you can easily add the method yourself by adding the implementation from this Mozilla Dev Center article.

like image 165
Daniel Vassallo Avatar answered Oct 14 '22 21:10

Daniel Vassallo


Finally done, it was interesting for me so I spent some time trying to come up with something, and here it's

It overrides browser's setTimeout and fill active status of current active calls in window._activeSetTimeouts hash, with window._showCurrentSetTimeouts() demo function that displays current setTimeout calls that are waiting.

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);
like image 29
aularon Avatar answered Oct 14 '22 19:10

aularon