10

I am trying to add my own error handling to the JavaScript setTimeout function. The following code works fine in chrome:

var oldSetTimeout = window.setTimeout;
window.setTimeout = function setTimeout(func, delay) {
    var args = Array.prototype.slice.call(arguments, 0);
    args[0] = function timeoutFunction() {
        var timeoutArgs = Array.prototype.slice.call(arguments, 0);
        try {
            func.apply(this,timeoutArgs);
        }
        catch (exception) {
            //Do Error Handling
        }
    }
    return oldSetTimeout.apply(this, args);
}

But in IE7 it turns into a recursive function. For some reason oldSetTimeout gets set to the new function.

Any suggestions?



side note: Yes, I need to do it this way. I am using a pile of 3rd party libraries all of which don't deal with setTimeout well, so I can't just change the calls to setTimeout.
alumb
  • 4,401
  • 8
  • 42
  • 52

2 Answers2

23

This is because you're using named function expressions, which are incorrectly implemented in IE. Removing the function names will fix the immediate problem. See kangax's excellent article on this subject. However, there's another problem that isn't so easily fixed.

In general, it's not a good idea to attempt to override properties of host objects (such as window, document or any DOM element), because there's no guarantee the environment will allow it. Host objects are not bound by the same rules as native objects and in essence can do what they like. There's also no guarantee that a host method will be a Function object, and hence oldSetTimeout may not have always have an apply() method. This is the case in IE, so the call to oldSetTimeout.apply(this, args); will not work.

I'd suggest the following instead:

window.oldSetTimeout = window.setTimeout;

window.setTimeout = function(func, delay) {
    return window.oldSetTimeout(function() {
        try {
            func();
        }
        catch (exception) {
            //Do Error Handling
        }
    }, delay);
};
Community
  • 1
  • 1
Tim Down
  • 318,141
  • 75
  • 454
  • 536
  • Its 2019 now, is there still and with overriding global functions and should it be avoided. I do not want to support ANY IE version at all. I only tested some in latest Firefox and it works perfectly fine. – redanimalwar Oct 23 '19 at 21:02
  • @redanimalwar: In general, I'd still recommend against overriding built-in functions and host methods simply because of all the code that relies on them. That said, the behaviour of host methods is specified in much more detail now than in 2010 so it's often a lot safer to override them now. – Tim Down Oct 24 '19 at 14:42
4

Minor improvement to the Answer of Tim Down to mimic the original even more:

window.oldSetTimeout = window.setTimeout;
window.setTimeout = function(func, delay) {
    return window.oldSetTimeout(function() {
        try {
            func();
        }
        catch (exception) {
            //Do Error Handling
        }
    }, delay);
};
Tim
  • 833
  • 11
  • 11
  • Good point. I made the change to my answer; I hope you don't mind. – Tim Down Dec 11 '13 at 12:21
  • 1
    @Meetai.com Hi! You should have contributed with a comment or even an edit suggestion, but not an answer :( [more info](https://stackoverflow.com/help/privileges/comment) – Neithan Max Nov 07 '19 at 13:38
  • @CarlesAlcolea: We tried that but it would completely obliterate the code format. – Meetai.com Mar 13 '20 at 22:04