Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

javascript

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.

like image 428
aroth Avatar asked Apr 28 '11 11:04

aroth


People also ask

What does clearTimeout do in JavaScript?

The global clearTimeout() method cancels a timeout previously established by calling setTimeout() .

What is the alternative for setTimeout in JavaScript?

The setInterval method has the same syntax as setTimeout : let timerId = setInterval(func|code, [delay], [arg1], [arg2], ...) All arguments have the same meaning. But unlike setTimeout it runs the function not only once, but regularly after the given interval of time.

Why JavaScript timer is unreliable?

Even more concerning is the fact that it resumes from the same time it paused on, missing the time period in between. So, if we create any mission critical application in Javascript which uses timer, the result would be catastrophic. The reason why this happens is because Javascript is single threaded.

Is setTimeout deprecated in JavaScript?

We all know that passing a string to setTimeout (or setInterval ) is evil, because it is run in the global scope, has performance issues, is potentially insecure if you're injecting any parameters, etc. So doing this is definitely deprecated: setTimeout('doSomething(someVar)', 10000);


4 Answers

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?

like image 130
sharp johnny Avatar answered Sep 29 '22 13:09

sharp johnny


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.

like image 44
Gareth Avatar answered Sep 29 '22 14:09

Gareth


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.

like image 31
Bar Goldinfeld Avatar answered Sep 29 '22 13:09

Bar Goldinfeld


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.

like image 31
Lawrence Cherone Avatar answered Sep 29 '22 15:09

Lawrence Cherone