每当事件处理程序内发生错误时,它就会完全停止代码执行,因此不会调用第二个事件回调。
例如:
$(function() {
window.thisDoesntExist();
}
$(function() {
//Do something unharmful and unrelated to the first event
}
您可以通过在两个匿名函数中添加try / catch来轻松解决此(简化)示例中的问题,但实际上这些函数通常会添加其他几个事件处理程序,而这些处理程序又需要try / catch。我最终得到了带有try / catch块的非常重复的代码。
我的项目采用模块化设计,每个功能都在不同的JS中(并在构建过程中连接)。我正在寻找一种更通用的方法来处理每个功能中的错误,以便错误不会阻止其他功能的代码执行。
我已经尝试过以下解决方案: - window.onerror(即使你在这个函数中返回true,代码执行也会停止) - $(window).error()=>不推荐使用,代码执行停止
答案 0 :(得分:5)
您可以创建一个辅助函数来防止重复相同的样板代码。
function tryFunction(f, onerror) {
try {
if (typeof f == 'function') {
return f();
}
} catch (e) {
return onerror(e);
}
}
$(function() {
var result = tryFunction(window.thisDoesNotExist, function (error) {
alert('Whoops: ' + error);
});
});
I created a little demonstration。它略有不同,但思路相同。
答案 1 :(得分:0)
您可以在致电if (typeof myFunction == 'function')
myFunction()
并且可选地将它包装在像Bart所说的通用函数中,如果你的函数不存在,可以选择在控制台中记录错误。
如果你的webapp很多,有许多交互和JS,那么try catch
太多可能会改变你的应用程序的全局性能。
答案 2 :(得分:0)
我会尝试这样的东西,用一个包装器来处理你的try catch(见下文,或者这个jsfiddle:http://jsfiddle.net/TVfCj/2/)
从我(不是,不是真的)处理 this 和参数的方式来看,我想很明显我是以js开头的。但我希望你能得到这个想法,这是正确/有用的。
var wrapper = {
wrap: function wrap(f) {
return function (args) {
try {
f.apply(null, args);
} catch (ex){
console.log(f.name+" crashed with args "+args);
};
};
}
};
var f1 = function f1Crashes(arg) {
return window.thisDoesntExist();
};
var f2 = function f2Crashes(arg) {
return window.thisDoesntExist();
};
var f3 = function f3MustNotCrash(arg) {
wrapper.wrap(f1)(arg);
wrapper.wrap(f2)(arg);
}
f3('myarg');
答案 3 :(得分:0)
您在问题中提到的try
- catch
模式是正确的方式 - 您想要 try
- catch
块,< strong> not 一种无声地解决模块错误的方法(通常总是非常小心地处理全局和持续的异常,这种方式就是6个月后才发现的数据损坏错误。)
你真正的问题是:
...实际上这些函数通常会添加其他几个事件处理程序,而这些处理程序又需要try / catch。我最终得到了带有try / catch块的非常重复的代码。
对此的修正是Promise
。这是一个新的结构,在大多数浏览器中都是原生的,但在慢速浏览器中很容易填充(ahem,IE),它为您提供了一种管理事件回调和事件异常的标准方法。 / p>
使用Promise
您的代码会承诺始终执行某些操作:解析/成功或拒绝/失败。
function moduleA() {
return new Promise(function (resolve, reject)
{
try{
var result = window.thisDoesntExist();
resolve(resolve); // Success!
}
catch(err){
reject(err); // Fail!
}
});
}
这样做更好,因为您可以在每个回调中嵌套try
- catch
块,而不是链接承诺:
moduleA().
then(moduleB).
then(moduleC).
catch(errorHandler); // Catch any error from A, B, or C
您也可以处理错误并继续:
moduleA().
catch(continuableErrorHandler). // Catch any error from A
then(moduleB).
then(moduleC).
catch(errorHandler); // Catch any error from B or C
在回调中你仍然需要很多try
- catch
块,但是Promise
中包含的任何内容都可以采用相同的模块化方式处理。
JS中的下一个是async
和await
,但您现在可以将它们与转换器一起使用。这些使用promises来使代码更容易阅读,最重要的是(对你而言)在顶部有一个try
- catch
,它从整个Promise
链中收集异常。
这个答案已经太久了,但我blogged about that in more detail。
TL; DR:如果您的问题是“非常重复[事件回调]代码填充了try / catch块”请尝试使用Promise
。< / p>
答案 4 :(得分:-2)
我找到了解决方案。当使用setTimeout时,代码在一个单独的线程中执行,因此它不会破坏网页的任何其他部分。
$(function() {
setTimeout(function() {
window.thisDoesntExist();
}, 0);
});
$(function() {
setTimeout(function() {
//Do something unharmful and unrelated to the first event
alert("This passes")
}, 0);
});
在此示例中,即使第一个函数抛出错误,也会运行第二个函数。 这是一个有效的例子:http://jsfiddle.net/mathieumaes/uaEsy/