Как я могу показать список всех потоков, созданных setTimeout/setInterval
Я хочу сделать это либо чистым javascript, либо любой консолью в браузере или что-то еще.
Возможно ли это?
Спасибо
Дальнейшие объяснения:
Я хочу отлаживать библиотеку, которая выполняет анимацию. Я хочу знать, создано ли несколько таймеров, если есть несколько анимированных объектов.
Ответы
Ответ 1
Как уже упоминалось, setTimeout
не создает поток. Если вам нужен список всех идентификаторов таймаута (например, вы можете их отменить), то см. Ниже:
Я не думаю, что вы можете получить список всех идентификаторов timeout без изменения кода при их вызове. setTimeout
возвращает id, и если вы его игнорируете, то это недоступно для вашего JavaScript. (Очевидно, у переводчика есть доступ к нему, но ваш код этого не делает.)
Если вы можете изменить код, вы можете это сделать:
var timeoutId = [];
timeoutId.push(setTimeout(myfunc, 100));
... Убедитесь, что timeoutId
объявлен в глобальной области (возможно, используя window.timeoutId = []
).
Сверху моей головы, но для переопределения setTimeout
вам нужно сделать что-то вроде этого:
var oldSetTimeout = setTimeout;
setTimeout = function (func, delay) {
timeoutId.push(oldSetTimeout(func, delay));
}
Это не проверено, но оно дает вам отправную точку. Хорошая идея, волк!
Изменить: ответ aularon дает гораздо более полное воплощение вышеуказанной идеи.
Ответ 2
Обратите внимание, что setTimeout()
не создает новые потоки. Сценарий на стороне браузера не только однопоточный, но и оценка JavaScript разделяет один и тот же единственный поток с рендерингом страницы (веб-работники).
Дальнейшее чтение:
Вы можете сами создать диспетчер таймера:
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;
}
};
})();
Затем используйте его следующим образом:
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);
Вышеуказанный результат отобразит следующий результат в консоли:
// Number of Timers at Start: 2
// Timer t1 triggered after 1 second
// Timer t2 triggered after 5 second
// Number of Timers at End: 0
Обратите внимание, что вышеприведенная реализация timerManager
использует метод Array.indexOf()
. Это было добавлено в JavaScript 1.6 и поэтому не реализовано всеми браузерами. Однако вы можете легко добавить этот метод самостоятельно, добавив реализацию из этой статьи Mozilla Dev Center.
Ответ 3
Наконец, это было интересно для меня, поэтому я потратил некоторое время на то, чтобы придумать что-то, и вот он
Он переопределяет браузер setTimeout
и заполняет активное состояние текущих активных вызовов в хеше window._activeSetTimeouts
, с демонстрационной функцией window._showCurrentSetTimeouts()
, которая отображает текущие ожидающие вызовы setTimeout
.
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);