Viewing all the timeouts/intervals in javascript?

Viewed 97800

I'm writing an application that utilizes JavaScript timeouts and intervals to update the page. Is there a way to see how many intervals are setup? I want to make sure that I'm not accidentally going to kill the browser by having hundreds of intervals setup.

Is this even an issue?

7 Answers

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.

window.originalSetTimeout = window.setTimeout;
window.originalClearTimeout = window.clearTimeout;
window.activeTimers = 0;

window.setTimeout = function(func, delay) {
    window.activeTimers++;
    return window.originalSetTimeout(func, delay);
};

window.clearTimeout = function(timerID) {
    window.activeTimers--;
    window.originalClearTimeout(timerID);
};

Of course, you might not always call clearTimeout, but this would at least give you some way to track what is happening at runtime.

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

Related