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



我开始在我的javascript对象中添加错误处理,这些对象通常使用jQuery。我遇到的问题是,当我从jQuery方法中抛出new Error时——它不会被包装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);
    }
});

你知道如何简化它吗?为什么它会这样?

在第一个示例中,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);
        }
    );
);

最新更新