jQuery方法抛出新的错误 - 没有被外部的try / catch块捕获

时间:2014-06-05 08:38:28

标签: javascript jquery error-handling javascript-objects

我开始在我的javascript对象中添加错误处理,这些对象经常使用jQuery。 我遇到的问题是,当我从jQuery方法中抛出新的错误时 - 它不会被包装jquery调用的catch语句捕获 - 它只是抛出标准错误,但不会作为日志消息登录到控制台。这是一个例子:

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);

        }

    }

};

当我用try / catch包装回调函数的内容时 - 它可以工作:

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

    try {

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

        throw new Error('callPage method failed');

    } catch(errorMessage) {

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

    }

});

知道如何简化这个以及它为什么会这样做?

1 个答案:

答案 0 :(得分:3)

在第一个示例中,try/catch保护设置事件处理程序的代码,而不是事件处理程序本身的代码。在触发事件之前,该代码不会运行,此时执行早已离开try块。

考虑这个等效的例子:

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

foo();

您不会指望调用foo导致的错误只是因为当foo被定义为执行时try块内。

正如您所示,一个解决方案当然是在可能抛出的函数体内使用try/catch。另一种解决方案是创建一个可重用的“捕获包装器”函数,可能是这样的:

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);
        }
    );
);