Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to catch exceptions thrown in callbacks passed to jQuery?

I'd like to catch exceptions thrown from callbacks passed to jQuery (either to event handlers like click, or to jqXHR methods such as then or always).

I've identified two options:

  • window.onerror handler - this is only a partial solution because it isn't supported on Android which is one of my target platforms
  • handling exceptions within each individual callback - not DRY at all!

The only other thing I can think of is overriding jQuery methods but that can result in problems any time I upgrade jQuery. For AJAX handlers, I could possibly use $.ajaxSetup (per the answer to Exceptions thrown in jQuery AJAX callbacks swallowed?) but I'm not sure that will allow me to catch everything.

Are there any other options?

like image 733
Alex Korban Avatar asked Mar 08 '12 04:03

Alex Korban


1 Answers

You can wrap each callback like this:

function cbWrapper(fn) {
    return function() {
        try {
            return(fn.apply(this, arguments));
        } catch(e) {
            // handle all your exceptions here
        }
    };
}

So, when you go to pass a callback to an Ajax call, instead of passing the actual callback, you pass cbWrapper(callback).

$.get(url, cbWrapper(myRealCallback));

Or the inline anonymous version would be like this:

$.get(url, cbWrapper(function() {
    // actual callback code here
}));

A more advanced way of doing it would be to override $.get() with your own implementation that wraps the callback automatically, but that gets tricky because jQuery is so flexible about what arguments are actually passed. Because of that and because you have to override one specific argument to make this work, you would have to duplicate all of their argument detection code that figures out which arguments are present and which correspond to which actual function parameters. That code is a bit messy. It's doable and probably won't break because if jQuery broke it, then existing jQuery code would break, but it isn't very clean.

If it's all your own code, you could just make your own version of $.get() that isn't so flexible with argument positions and switch all of your code to use it instead of the actual $.get():

jQuery.fn.myGet = function(url, fn) {
    return(jQuery.get(url, cbWrapper(fn)));
}
like image 121
jfriend00 Avatar answered Sep 17 '22 12:09

jfriend00