2009-12-11 68 views
14

我正在開發JS在Web框架中使用,並經常與其他開發人員(通常容易出錯)的jQuery代碼混合使用。不幸的是,他們的jQuery(document).ready塊中的錯誤阻止了我的執行。採取以下簡單示例:在jQuery中處理錯誤(文檔).ready

<script type="text/javascript"> 
    jQuery(document).ready(function() { 
     nosuchobject.fakemethod();  //intentionally cause major error 
    }); 
</script> 
<script type="text/javascript"> 
    jQuery(document).ready(function() { 
     alert("Hello!");     //never executed 
    }); 
</script> 

不應該第二個就緒塊執行,不管前面發生了什麼?是否有一種「安全」的方式來運行即使在以前的錯誤情況下也能運行的jQuery(document).ready?

編輯:我沒有控制/對易錯塊的可見性,因爲它們是由其他作者編寫的,任意混合使用。

回答

13

我沒試過這個代碼,但它應該工作(至少,這個想法應該是這樣)。 確保在jQuery之後包含它,但是在任何可能有問題的腳本之前。(不是必須的,看評論。)

var oldReady = jQuery.ready; 
jQuery.ready = function(){ 
    try{ 
    return oldReady.apply(this, arguments); 
    }catch(e){ 
    // handle e .... 
    } 
}; 
+0

這似乎工作得很好,無論它是在潛在有問題的腳本之前還是之後。我想我要做的就是將我準備好的塊的內容(樣本中的alert(「Hello!」))移到catch塊之後。這樣,我的就緒塊可以「自己」附加到先前就緒塊的末尾。 – 3hough 2009-12-11 20:31:04

+0

偉大的解決方案。從來沒有想到這一點。 – 2009-12-11 20:35:07

+0

不知道我在想什麼,但是無論它走到哪裏,只要它在標記中,而不是在某個onload事件中,它就會起作用,因爲我們在dom負載調用之前劫持ready方法。 – jvenema 2009-12-11 21:35:51

1

您是否試圖在try ... catch括號中包含容易出錯的命令?

$(function(){ 
    try { 
     noObject.noMethod(); 
    } catch (error) { 
     // handle error 
    } 
}); 

$(function(){ 
    try { 
     alert("Hello World"); 
    } catch (error) { 
     // handle error 
    } 
}); 

爲了避免潛在的混亂,$(function(){ ... });在功能上相同$(document).ready(function(){ ... });

+0

的問題是,我沒有在拋出錯誤的塊控制/可視性。在上面的示例中,第一個jQuery(document).ready塊來自其他人的代碼。因此不幸的是,我沒有辦法將它們包裝在try/catch塊中。 這是一個Web框架的一部分,任意插件可以在文檔的頭部加載到一起。 – 3hough 2009-12-11 20:11:22

+2

您應該在您的問題中提及您無權訪問其代碼。 – Sampson 2009-12-11 20:12:14

-2

,你可以再參考jQuery的每個代碼塊之前。然後你的代碼將使用庫的新實例,並執行它。我已經在OSX上的Safari 4.0.3中測試過了。

<html> 
<head> 
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script> 
    <script type="text/javascript"> 
     jQuery(document).ready(function() { 
            nosuchobject.fakemethod();       //intentionally cause major error 
        }); 
    </script> 
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>  
    <script type="text/javascript"> 
        jQuery(document).ready(function() { 
            alert("Hello!");                 //executed! 
        }); 
    </script> 

</head> 
<body> 

<p>hello world</p> 

</body> 
</html> 
+0

糟糕的想法......這至少會迫使用戶下載庫兩次,並可能導致靜態變量和對象被覆蓋的問題。 – jvenema 2009-12-11 20:15:14

+0

用戶的瀏覽器只在緩存攔截器放置到位時重新下載遠程文件。在我的示例中,瀏覽器從緩存中讀取第二個jQuery參考。它並不漂亮,但它有助於解決原始問題。關於靜態變量和對象的問題,你的意思是在jQuery庫本身,或用戶定義的靜態變量和對象?在覆蓋的情況下,jQuery自身映射。在我的示例中,正確編寫的第二個塊將引用jQuery的新實例。你能否詳細說明你提到的問題?謝謝! – simeonwillbanks 2009-12-11 20:56:56

+0

在jquery的開頭,你會看到:jQuery.fn = jQuery.prototype = {...}。由於這些對象沒有被擴展但是被實例化,任何修改或觸及這些屬性的東西(事實上,在jquery級別靜態設置的任何東西)都將被丟棄。即使瀏覽器確實緩存了js,它仍然需要重新解析它並重新加載所有已聲明的元素,從而降低用戶體驗(更不用說它可能會引入內存泄漏,因爲沒有任何dom的清理事件)。 – jvenema 2009-12-11 21:40:13

2

要回答你的問題,無論是ready塊基本上組合成一個給定的jQuery的工作方式:

<script type="text/javascript"> 
    jQuery(document).ready(function() { 
     nosuchobject.fakemethod();  //intentionally cause major error 
     alert("Hello!");     //never executed 
    }); 
</script> 

所以這就是爲什麼它不是每個錯誤警報上方。我不相信有一種方法可以解決這個問題,使每個ready函數都能運行,而不管前面的失敗。

1

這裏是解決方案,將包裹送到願與try-catch塊的任何功能:

(function($){ 
    $.fn.oldReady = $.fn.ready; 
    $.fn.ready = function(fn){ 
     return $.fn.oldReady(function(){ try{ if(fn) fn.apply($,arguments); } catch(e){}}); 
    } 
})(jQuery);