[英]Javascript error stops code execution
每當事件處理程序內發生錯誤時,它就會完全停止代碼執行,因此不會調用第二個事件回調。
例如:
$(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()=>不推薦使用並且代碼執行停止
您可以創建一個輔助函數來防止重復相同的樣板代碼。
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);
});
});
我創建了一個小演示 。 它略有不同,但同樣的想法。
你可以在調用myFunction()
之前調用if (typeof myFunction == 'function')
myFunction()
並且可選地將其包裝在像Bart所說的通用函數中,以便在您的函數不存在時可以選擇在控制台中記錄錯誤。
如果您的webapp很多,有很多交互和JS,那么try catch
太多會改變應用程序的全局性能。
我會嘗試這樣的東西用一個包裝器來處理你的try catch(見下文,或者這個jsfiddle: http : //jsfiddle.net/TVfCj/2/ )
從我(不是,而不是真的)處理這個和論點的方式來看,我想很明顯我是從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');
您在問題中嘗試嘗試的try
catch
模式是正確的方法 - 您希望 try
- catch
塊, 而不是靜默地通過模塊錯誤(通常總是非常小心地處理全局和持續的異常,這種方式是數據損壞6個月之后你才發現的錯誤)。
你真正的問題是:
...實際上,這些函數通常會添加其他幾個事件處理程序,而這些處理程序又需要try / catch。 我最終得到了帶有try / catch塊的非常重復的代碼。
對此的解決方案是Promise
。 這是一種新結構,在大多數瀏覽器中都是原生的,但在慢速瀏覽器中很容易填充(ahem,IE),這為您提供了一種管理事件回調和事件異常的標准方法。
使用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
鏈中的異常。
這個答案已經太長了,但我已經在博客中詳細介紹了這一點 。
TL; DR:如果您的問題是“非常重復[事件回調]代碼填充了try / catch塊”,請嘗試使用Promise
。
我找到了解決方案。 使用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/
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.