2010-09-02 12 views
15

Chcę to zrobić przez czysty javascript lub jakiejkolwiek konsoli w przeglądarce lub cokolwiek innego.Jak mogę wyświetlić listę wszystkich wątków uruchomionych przez setTimeout/setInterval

Czy to możliwe?

Dzięki

Dalsze wyjaśnienia: Chcę debugowania biblioteki, które wykonuje animacje. Chcę wiedzieć, czy utworzono wiele timerów, jeśli animowanych jest wiele obiektów.

+0

Mike, czy możesz dodać więcej szczegółów? –

+1

Czy chcesz wyświetlić tylko listę identyfikatorów przekroczenia limitu czasu? javascript nie używa wątków ... – brad

Odpowiedz

6

Jak wspomnieli inni, setTimeout nie odradza się wątku. Jeśli chcesz otrzymać listę wszystkich identyfikatorów Timeout (dzięki czemu można je anulować, na przykład), a następnie zobaczyć poniżej:


Nie sądzę, można uzyskać listę wszystkich identyfikatorów limitu czasu bez zmiany kodu podczas nazywają się. setTimeout zwraca identyfikator - a jeśli go zignorujesz, oznacza to, że jest on niedostępny dla skryptu JavaScript. (Oczywiście interpreter ma do niego dostępu, ale kod nie robi.)

Jeśli można zmienić kod można to zrobić:

var timeoutId = []; 

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

... Upewniwszy się, że timeoutId jest zadeklarowana w zakresie globalnym (być może za pomocą window.timeoutId = []).


Tuż przy mojej głowie, ale reimplement setTimeout trzeba by zrobić coś takiego:

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

to nie jest badana, ale daje punkt wyjścia. Dobry pomysł, molf!

Edytuj:aularon's answer podaje o wiele dokładniejszą implementację powyższego pomysłu.

+3

Można faktycznie przedefiniować 'setTimeout()' do przechowywania identyfikatorów w tablicy gdzieś. W ten sposób żaden kod nie musi być modyfikowany, po prostu trzeba wstrzyknąć trochę kodu Javascript przed jego wykonaniem. – molf

+0

@molf, jak to zrobić? –

+0

@molf dobry punkt. – Skilldrick

10

Pamiętaj, że setTimeout() nie odradza nowych wątków. Skrypty po stronie przeglądarki są nie tylko pojedynczym wątkiem, ale ocena JavaScript dzieli ten sam pojedynczy wątek z renderowaniem strony (niezależnie od siebie).

Dalsze czytanie:

Możesz budować menedżera timera siebie:

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

następnie używać go w sposób następujący:

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

Powyższy wyświetli następujący wynik w konsoli:

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

Należy zauważyć, że realizacja timerManager powyżej stosuje metodę Array.indexOf(). Zostało to dodane w JavaScript 1.6 i dlatego nie jest zaimplementowane we wszystkich przeglądarkach. Możesz jednak łatwo dodać metodę samodzielnie, dodając implementację od this Mozilla Dev Center article.

+0

Dzięki {Thanks} Popatrzę na ten –

+0

Artykuł John Resig jest bardzo przydatny, prawdopodobnie najlepszym wytłumaczeniem asynchronicznych zdarzeń pojedynczego wątku, z którymi miałem do tej pory do czynienia. Dziękuję również za doskonały kod. – Bob

8

końcu zrobić, to było interesujące dla mnie więc spędziłem trochę czasu próbując coś wymyślić, a here it's

To nadpisuje przeglądarki setTimeout i wypełnić aktywny status bieżących aktywnych połączeń w window._activeSetTimeouts hash z window._showCurrentSetTimeouts() funkcji demo wyświetla bieżące połączenia setTimeout, które czekają.

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

Bardzo dobrze, czapki do głowy! – Skilldrick

+0

nieco późno, ale dziękuję za tę odpowiedź, bardzo przydatne. Jednak musiałem zmienić wywołanie 'cb();' w 4. wierszu 'window.setTimeout': przedłożony argument w setTimeout może być funkcją lub ciągiem znaków niektórych kodu javascript. – BiAiB

+0

* clap * ... * clap * ... * clap * .. * clap * * clap * * clap * * clap * * brawa *. Niesamowity. Dziękuję bardzo za udostępnienie! – Mike

Powiązane problemy