aroth
aroth

Reputation: 54816

JavaScript - Is it possible to view all currently scheduled timeouts?

So I was wondering, is there any feasible way in JavaScript to view information about scheduled timeouts and intervals that you don't explicitly know about (I know setTimeout and setInterval return a handle that can be used to refer to the scheduled instance, but say that this is unavailable for one reason or another)? For instance, is there a way to use a tool like Chrome's JavaScript console to determine what timeouts are currently active on an arbitrary page, when they will fire, and what code will be executed when they fire? More specifically, say a page has just executed the following JavaScript:

setTimeout("alert('test');", 30000);

Is there some code I can execute at this point that will tell me that the browser will execute alert('test'); 30 seconds from now?

It seems like there theoretically should be some way to get this information since pretty much everything in JavaScript is exposed as a publicly accessible property if you know where to look, but I can't recall an instance of ever doing this myself or seeing it done by someone else.

Upvotes: 51

Views: 23697

Answers (4)

Lawrence Cherone
Lawrence Cherone

Reputation: 46610

You could also create a timer manager module which will keep track of current timers and allow you to get, add, stop and stop all timers.

var timers = (function() {
  //
  var timers = []

  //
  const getIndex = (array, attr, value) => {
      for (let i = 0; i < array.length; i += 1) {
          if (array[i][attr] === value) {
              return i
          }
      }
      return -1
  };

  // add
  const add = (callback, time) => {
    var id = setTimeout(() => {
      let index = getIndex(timers, 'id', id)
      timers.splice(index, 1)
      callback()
    }, time)
    timers.push({
      id: id,
      time: time,
      debug: callback.toString()
    })
  };

  // get all active timers
  const all = () => timers

  // stop timer by timer id
  const stop = (id) => {
    if (!isNaN(id)) {
      let index = getIndex(timers, 'id', id)
      if (index !== -1) {
        clearTimeout(timers[index].id)
        timers.splice(index, 1)
      }
    }
  };

  // stop all timers
  const stopAll = () => {
    for (let i = 0; i < timers.length; i++) {
      clearTimeout(timers[i].id)
    }
    timers = []
  };

  return {
    add: add,
    all: all,
    stop: stop,
    stopAll: stopAll,
  };
})();

//
timers.add(function() {
  console.log("timeout 1 fired");
}, 1000)

timers.add(function() {
  console.log("timeout 2 wont get fired");
}, 2000)

timers.add(function() {
  console.log("timeout 3 fired");
}, 3000)

timers.add(function() {
  console.log("timeout 4 fired, timers", timers.all());
}, 4000)

timers.add(function() {
  console.log("timeout 5 fired");
}, 5000)

console.log('All timers', timers.all())

console.log("kill timer 2")
timers.stop(2)

Run the snippet to see it in action.

Upvotes: 3

Bar Goldinfeld
Bar Goldinfeld

Reputation: 221

We've just published a package solving this exact issue.

npm install time-events-manager

With that, you can view them via timeoutCollection & intervalCollection objects.

Upvotes: 4

sharp johnny
sharp johnny

Reputation: 814

how about simply rewriting the setTimeout function to sort of inject custom logging functionality?

like

var oldTimeout = setTimeout;
window.setTimeout = function(callback, timeout) {
  console.log("timeout started");
  return oldTimeout(function() {
    console.log('timeout finished');
    callback();
  }, timeout);
}

might work?

Upvotes: 19

Gareth
Gareth

Reputation: 138082

No, even the HTML5 spec (which is a rationalisation of the HTML 4.01 behaviour in current browsers, with additional features) doesn't specify a way to list the available callbacks.

Upvotes: 8

Related Questions