I don't think there is a way to enumerate active timers, but you could override window.setTimeout and window.clearTimeout and replace them with your own implementations which do some tracking and then call the originals.
Instead of just have a count of timers, here is an implementation which stores all timerid's into an array. It only shows active timers while the accepted answer only counts calls to setTimeout & clearTimeout.
(function(w) {
var oldST = w.setTimeout;
var oldSI = w.setInterval;
var oldCI = w.clearInterval;
var timers = [];
w.timers = timers;
w.setTimeout = function(fn, delay) {
var id = oldST(function() {
fn && fn();
removeTimer(id);
}, delay);
timers.push(id);
return id;
};
w.setInterval = function(fn, delay) {
var id = oldSI(fn, delay);
timers.push(id);
return id;
};
w.clearInterval = function(id) {
oldCI(id);
removeTimer(id);
};
w.clearTimeout = w.clearInterval;
function removeTimer(id) {
var index = timers.indexOf(id);
if (index >= 0)
timers.splice(index, 1);
}
}(window));
This is how you can get the count of active timers on the page:
timers.length;
This is how you can remove all active timers:
for(var i = timers.length; i--;)
clearInterval(timers[i]);
Known limitations:
You can only pass a function (not a string) to setTimeout with this monkey patch.
The function assumes clearInterval and clearTimeout do the same, which they do but it could change in the future.
Based on @Alessio's answer. Below is my version. Has a bit more functionality for logging and inspection.
Here is some boilerplate that you can alter to utilize your own frameworks:
var s$ = function (s){return new String(s)}
var _w=window
_w.q$ = {
getMachineTimeMS: function(){
var d = new Date(), ms = d.getMilliseconds()
var a = [d.getHours(), d.getMinutes(), d.getSeconds(), '-', ms<10?'00' + s$(ms):ms<100?'0'+s$(ms):ms]
return a.join('')
}
,getCaller: function(opts){
return "(implement this)"
}
}
Here is the main code:
_w.setTimeout = function (orig_setTimeout) {
var t=(_w._Timers = _w._Timers||{})
var d=(t.Timeouts = t.Timeouts||{})
d.Active = d.Active||{}
t.z_to_id_idx = t.z_to_id_idx||{}
return function (h, n) {
var t = _w._Timers, d = t.Timeouts
var id = orig_setTimeout(h, n), ts = q$.getMachineTimeMS()
var c = q$.getCaller({depth:2})
t.z_to_id_idx[s$(id)] = d.Active[ts] = {sts: ts, id: id, h: h, n: n, scaller: c}
return id;
}
}(_w.setTimeout);
_w.clearTimeout = function (orig_clearTimeout) {
var t=_w._Timers, d = t.Timeouts
d.Inactive = d.Inactive||{}
return function new_clearTimeout(id) {
var t = _w._Timers, d = t.Timeouts, sId = s$(id)
if (!d.Active || !sId in t.z_to_id_idx) return
var r = t.z_to_id_idx[sId]
r.ccaller = q$.getCaller({depth:2})
r.cts = q$.getMachineTimeMS()
d.Inactive[r.ts] = r;
orig_clearTimeout(r.id);
delete d.Active[r.ts]
delete t.z_to_id_idx[sId]
}
}(_w.clearTimeout);
_w.setInterval = function (orig_setInterval) {
var t=(_w._Timers = _w._Timers||{})
var d=(t.Intervals = t.Intervals||{})
d.Active = d.Active||{}
t.z_in_id_idx = t.z_in_id_idx||{}
return function (h, n) {
var t = _w._Timers, d = t.Intervals
var id = orig_setInterval(h, n), ts = q$.getMachineTimeMS()
var c = q$.getCaller({depth:2})
t.z_in_id_idx[s$(id)] = d.Active[ts] = {sts: ts, id: id, h: h, n: n, scaller: c}
return id;
}
}(_w.setInterval);
_w.clearInterval = function (orig_clearInterval) {
var t=_w._Timers, d = t.Intervals
d.Inactive = d.Inactive||{}
return function new_clearInterval(id) {
var t = _w._Timers, d = t.Intervals, sId = s$(id)
if (!d.Active || !sId in t.z_in_id_idx) return
var r = t.z_in_id_idx[sId]
r.ccaller = q$.getCaller({depth:2})
r.cts = q$.getMachineTimeMS()
d.Inactive[r.ts] = r;
orig_clearInterval(r.id);
delete d.Active[r.ts]
delete t.z_in_id_idx[sId]
}
}(_w.clearInterval);
Usage example:
id = setTimeout(()=>{console.log("CALLED")}, 10000)
clearTimeout(id)
setInterval(()=>{console.log("CALLED")}, 1000)
console.table(_w._Timers.Timeouts.Inactive)
The console.table will output a nicely formatted and inspectable table in the JavaScript Console