10

We allow users to write code which sometimes calls jQuery.ready(function(){..}) multiple times. It seems like the first function call that throws an error prevents execution of the rest of the functions.

There was a discussion about this here with the solution wrapped jQuery.ready() in a delegate instead of wrapping the anonymous function parameter passed to jQuery.ready(..).

How can I override jQuery.ready(fn) and wrap the passed-in function parameter in a delegate which wraps it in try/catch and the passes to jQuery.ready(delegate)?

Here is an example:

<head>
  <script>
    // here is some code from third-party developer that sometimes throws an error
    jQuery.ready(function() {
      if ((new Date()).getMonth() == 0) 
        throw Error("It's January!");
    });
  </script>
</head>

<body>
  <script>
    // here is my code which should run regardless of the error in the <head> script
    jQuery.ready(function() {
      alert("I need to run even in January!");
    });
  </script>
</body>

What can I do to make code in run regardless of errors in ?

Community
  • 1
  • 1
alecswan
  • 3,670
  • 5
  • 25
  • 35
  • We cannot enclose the code in try-catch block because that code is provided by third-party developers. It's a similar problem the poster described in the referenced discussion. – alecswan Nov 22 '11 at 02:16
  • possible duplicate of [Handling errors in jQuery(document).ready](http://stackoverflow.com/questions/1890512/handling-errors-in-jquerydocument-ready) – ripper234 Apr 23 '12 at 08:54

3 Answers3

7

If you need to catch your own errors, then catch them with your own try/catch:

$(document).ready(function() {
   try {
       // put your normal code here
   } catch (e) {
       // put any code you want to execute if there's an exception here
   }
});

This will allow all subsequent code to continue without pause. One might ask why you're getting errors thrown? And perhaps what you should be doing to fix that or handle that more directly?

If you want, you could do this and replace all the troublesome calls to jQuery.ready() with jQuery.safeReady():

jQuery.fn.safeReady = function(f) {
    jQuery.ready(function() {
        try {
            f();
        } catch(e) {
            // make it so you can see errors in the debugger 
            // so you would know if something was wrong
            if (window.console) {
                console.log(e);
            }
        }
    });
};
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • I need to do something along the lines of your second code snippet. However, it doesn't seem to work because jQuery.ready(f) just queues up function f for later execution (when DOM is ready). When that happens execution of f throws an error preventing execution of other queued up functions. That's why in my original post I was asking how I can wrap the execution of function f in a try-catch delegate, such as safeF, before passing it to jQuery.ready(safeF)? – alecswan Nov 22 '11 at 16:26
  • @alecswan - good point, I've modified the second example in my answer to address that issue. – jfriend00 Nov 22 '11 at 16:31
  • You are not passing f parameters down, but I think this should work in this case because function f can never have any parameters when passed to jQuery.ready(f), right? – alecswan Nov 22 '11 at 16:53
  • Suppose I have some JavaScript code in which is contributed by third-party and my – alecswan Nov 22 '11 at 16:57
  • @alecswan - you can't pass parameters to a `.ready()` callback function so that is not an issue. – jfriend00 Nov 22 '11 at 17:02
  • @alecswan - Without seeing the particular code/issue that you're trying to work around, I can only think of three options: 1) Fix the cause of the exception so there is no longer an exception thrown. 2) Modify the version of jQuery used by the page to catch and ignore exceptions thrown in `.ready()` handlers. 3) Patch or modify the code throwing the exception. If you want further help in this direction, we will probably need to understand exactly why the exception is being thrown in the first place. – jfriend00 Nov 22 '11 at 17:09
  • @alecswan - One other idea. The issue is that jQuery's `.ready()` is getting aborted by the previous exception. If you made your own simple version of `.ready()` to trigger your code, then your initialization code would not be affected by other exceptions in jQuery's `.ready()`. Of course, other code in the page is probably not working right if jQuery's `.ready()` is being aborted so this may be only a bandaid that still has other issues until you fix the root cause of the exceptions. Here's one example: http://jsfiddle.net/jfriend00/Wh4zW/. – jfriend00 Nov 22 '11 at 17:15
  • I added a sample code in my original post to clarify my scenario. – alecswan Nov 22 '11 at 17:26
  • OK, very simple. If you can't run your code before the 3rd party code and you can't fix the cause of the exception, then your only two choices are 1) to patch the jQuery that the page uses to ignore the exception or 2) don't use `.ready()` to trigger your own code. `.ready()` will skip all other handlers if an exception is thrown. – jfriend00 Nov 22 '11 at 17:31
  • What about using a different instance of jQuery? Is it possible to use JavaScript scopes somehow? – alecswan Nov 22 '11 at 17:48
  • If your only issue is you need to just trigger your own `.ready()` code, then it's way better to just make your own `.ready()` tool rather than dupping all of jQuery. Or just use `$(window).load()` if you don't mind waiting for images to load. I don't know how to efficiently or safely run multiple instances of jQuery on the same page, nor would I recommend it. – jfriend00 Nov 22 '11 at 17:55
  • Instead of extending $.fn, would it be easier to just extend $ so that you can implement $.safeReady and not have safeReady a property of all jQuery objects? – kappasims Jan 18 '12 at 16:26
  • @kappasims - `$.fn` is actually `jQuery.prototype` so assigning to `$.fn` is just extending `$` and it doesn't cost you anything to have another property that's available on all jQuery objects. The prototype system is efficient that way. But, the safeReady function can be anything - it can even be a standalone global function if one wants. It's purely up to the implementor. – jfriend00 Jan 19 '12 at 01:22
1

It's worth knowing that in JQuery 3.0 this behavior has changed, and one error in JQuery.ready() will not prevent the rest from firing.

See official documentation here:

https://github.com/jquery/jquery/issues/1823

https://jquery.com/upgrade-guide/3.0/#breaking-change-document-ready-handlers-are-now-asynchronous

FarmerBob
  • 1,314
  • 8
  • 11
1

You can overwrite it like that:

jQuery.fn.ready = function(param){
    // do whatever you wish
};

but you should not do it. See this jsfiddle for a reason.

The example from my jsfiddle shows, that the above solution would also overwrite commonly used jQuery feature and can severely break your code.

Just rewrite your code - either by changing .ready() into .delegate() or by enclosing poorly written code within try {...} catch(...) {...} statements.

Tadeck
  • 132,510
  • 28
  • 152
  • 198
  • But if your `ready` handler is solid, it should not cause these kinds of problems ... I don't understand what your fiddle proves. http://jsfiddle.net/26KUU/ – ripper234 Apr 23 '12 at 08:52