簡體   English   中英

Javascript錯誤會停止代碼執行

[英]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).er​​ror()=>不推薦使用並且代碼執行停止

您可以創建一個輔助函數來防止重復相同的樣板代碼。

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中的下一個是asyncawait ,但你現在可以使用它們與一個轉換器。 這些使用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM