Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery method throw new Error - not catched by the outside try / catch block

I'm started adding error handling to my javascript objects, which very often use jQuery. The problem I have is that when I throw new Error from within jQuery method - it is not catched by the catch statement wrapping the jquery call - it simply throws the standard error, but does not log into the console as log message. Here's an example:

var MyNamespace = MyNamespace || {};

MyNamespace.Page = function() {};

MyNamespace.Page.prototype = {

    callPage : function() {

        "use strict";

        $(document).on('change', 'select', function(event) {

            event.preventDefault();
            event.stopPropagation();

            throw new Error('callPage method failed');

        });

    },

    init : function() {

        "use strict";

        try {

            this.callPage();

        } catch(errorMessage) {

            console.log('Error : ' + errorMessage);

        }

    }

};

When I wrap the content of the callback function with the try / catch - then it works:

$(document).on('change', 'select', function(event) {

    try {

        event.preventDefault();
        event.stopPropagation();

        throw new Error('callPage method failed');

    } catch(errorMessage) {

        console.log('Error : ' + errorMessage);

    }

});

Any idea how to streamline this and why does it behave this way?

like image 854
Spencer Mark Avatar asked Sep 11 '25 11:09

Spencer Mark


1 Answers

In the first example, the try/catch protects the code that sets the event handler, not the body of the event handler itself. That code doesn't run until the event is triggered, at which point execution has long since left the try block.

Consider this equivalent example:

try {
    var foo = function() {
        throw new Error("foo error");
    }
}
catch (error) {
}

foo();

You wouldn't expect the error caused by calling foo to be caught just because at the time foo was defined execution was inside the try block.

One solution is of course to use try/catch inside the body of the function that might throw, as you have shown. Another solution is to create a reusable "catching wrapper" function, perhaps like this:

function catchIfException(func, handler) {
    return function() {
        try {
            var args = Array.prototype.slice.call(arguments);
            func.apply(this, args);
        }
        catch (error) {
            handler(error);
        }
    };
}


$(document).on('change', 'select', 
    catchIfException(
        function(event) {
            event.preventDefault();
            event.stopPropagation();

            throw new Error('callPage method failed');
        }, 
        function(error) {
            console.log("error: " + error);
        }
    );
);
like image 94
Jon Avatar answered Sep 13 '25 00:09

Jon