2012-05-08 29 views
12

Tôi gặp sự cố khi gỡ lỗi các ứng dụng web của mình. Nó rất bực bội vì tôi đã cố gắng tái tạo vấn đề với một trang web nhỏ mà tôi có thể đăng trên jsfiddle, nhưng điều này có vẻ là một trường hợp của "Higgs-Bugson".Ngăn xếp cuộc gọi bị mất khi một ngoại lệ được ném trong trình xử lý jQuery

Tôi có trang web có trình xử lý jQuery(document).ready() lớn. Vấn đề là khi một ngoại lệ được ném từ bên trong trình xử lý jQuery(document).ready(), tôi nhận được một cuộc gọi ngăn xếp với một số hàm ẩn danh và không có con trỏ tới mã thực sự đã ném ngoại lệ.

Bất cứ khi nào tôi cố gắng tái tạo hành vi này với một trang web nhỏ, tôi luôn có được một con trỏ đến mã mà ném ngoại lệ, nhưng trong mã sản xuất, tôi không bao giờ có được con trỏ ngăn xếp. Điều này làm cho việc gỡ rối thêm bực bội và dễ bị lỗi.

Có ai ở đây có bất kỳ ý tưởng nào có thể gây ra hành vi này và cách thực hiện đúng không?


Cập nhật: Đã vài tháng kể từ khi tôi đăng câu hỏi này và bây giờ tôi tin rằng tôi đã thuyết phục sao chép vấn đề này. Tôi tạo lại vấn đề với HTML sau:

<html xmlns="http://www.w3.org/1999/xhtml" >  
<body> 
Factorial Page 
<input type='button' value='Factorial' id='btnFactorial' /> 
<script src="Scripts/jquery-1.6.1.js" type="text/javascript"></script> 
<script type='text/javascript'> 
    $(document).ready(documentReady); 

    function documentReady() { 
     $('#btnFactorial').click(btnFactorial_click); 

     factorial(-1); 
    } 

    function btnFactorial_click() { 
     var x; 
     x = prompt('Enter a number to compute factorial for.', ''); 
     alert(x + '! = ' + factorial(x)); 
    } 

    function factorial(x) { 
     if (x < 0) 
      throw new Error('factorial function doesn\'t support negative numbers'); 
     else if (x === 0 || x === 1) 
      return 1; 
     else 
      return factorial(x - 1) * x; 
    } 
</script>  
</body> 
</html> 

Nhìn vào mã, bạn sẽ thấy cảnh báo số của số bạn chỉ định. Nhập số âm và lỗi sẽ được tạo. Trong trường hợp này, Visual Studio sẽ bắt lỗi và làm nổi bật dòng mã nơi xảy ra lỗi và hiển thị ngăn xếp cuộc gọi bao gồm factorialbtnFactorial_click.

Mã này cũng gọi factorial(-1) từ trình xử lý $ (tài liệu) .ready. Trong trường hợp này, Visual Studio di chuyển nổi bật với khối finally trong mã jQuery sau (trích từ jquery-1.6.1.js, bắt đầu vào dòng 987

  // resolve with given context and args 
      resolveWith: function(context, args) { 
       if (!cancelled && !fired && !firing) { 
        // make sure args are available (#8421) 
        args = args || []; 
        firing = 1; 
        try { 
         while(callbacks[ 0 ]) { 
          callbacks.shift().apply(context, args); 
         } 
        } 
        finally { 
         fired = [ context, args ]; 
         firing = 0; 
        } 
       } 
       return this; 
      }, 

Mặc dù các cuộc gọi stack không được hiển thị, Visual Studio Lý do cho hành vi kỳ quặc này là gì và làm thế nào tôi có thể thiết kế ứng dụng của mình để tôi có thể dễ dàng bẫy các lỗi bắt nguồn từ các trình xử lý như $ (tài liệu) .đã có sẵn. ?

+5

+1 cho Higgs-Bugson –

+0

Bạn có thể đăng mẫu mã không? – izb

+0

@izb, sự cố luôn xuất hiện trong mã sản xuất của tôi (mà tôi không thể đăng ở đây), nhưng không bao giờ xuất hiện trong mã thử nghiệm mà tôi viết để cố tách biệt vấn đề. –

Trả lời

2

Tôi khuyên bạn nên tạo đối tượng được khởi tạo trong khối jQuery(document).ready(). Ví dụ:

var oStart = function(){ 
    var pageMethod = function(){ /*...*/ } 
    var pageMethodOther = function(){ /*...*/ } 
    /*...*/ 
    var init = function(){ 
     jQuery(document).ready(function(){ 
      /* do your stuff here */ 
     }); 
    } 
} 

oStart.init(); 

Điều này sẽ giúp bạn tách logic ứng dụng và logic chỉ jQuery. Bạn nên có rất ít trong khối sẵn sàng của bạn. Chỉ những thứ đó là hoàn toàn cần thiết sau khi DOM đã tải hoàn toàn. Mọi thứ khác sẽ có thể được tải vào bộ nhớ trong khi trang vẫn đang hiển thị.

+0

Mã này chưa được kiểm tra và được đăng để giải thích ý tưởng, chứ không phải mã sản xuất. : D – seangates

4

I'm having a problem debugging my web applications

Loại trình gỡ lỗi nào bạn đang sử dụng? Họ có xu hướng khác nhau và tốt nhất mà tôi đã tìm thấy khi phát triển là firefox vì một số công cụ tích hợp rất tốt đẹp mà họ có.

Mặc dù rất tốt để tái tạo một vấn đề, khi nó không thể được sao chép trong một ví dụ ngắn gọn đơn giản sau đó gỡ lỗi ngày càng trở nên quan trọng.Thiết lập điểm ngắt và đi từng dòng đôi khi là cách duy nhất thay vì chờ đợi lỗi xảy ra trong thời gian chạy và sau đó truy tìm lại.

Có một số cách tiếp cận được nêu trong bài viết MSDN này có thể hữu ích để giúp giải quyết vấn đề của bạn. Tôi chắc chắn bạn đã thử một số trong số đó, nhưng ít nhất đáng xem - đáng chú ý là "Kịch bản 3: Tôi gặp lỗi bên trong một tập hợp các phương thức trợ giúp và tôi không chắc chắn nơi có lỗi."

"Làm thế nào để gỡ lỗi mã jQuery của bạn"

http://msdn.microsoft.com/en-us/magazine/ee819093.aspx

Chỉnh sửa để đáp ứng với nội dung mới

jsfiddle nội dung mới: http://jsfiddle.net/EJbsS/

Khi chạy jsfiddle trong chrome, lần chạy đầu tiên thông qua giai thừa (-1) được gọi. Một lỗi xuất hiện. Nó có thể được truy cập bằng cách nhấp vào ở phía dưới bên phải tại x màu đỏ, hoặc bằng cách kiểm tra yếu tố, điều hướng đến tab giao diện điều khiển, và sau đó nhìn vào khu vực văn bản. Lỗi đúng đọc "Lỗi không bắt buộc: hàm giai thừa không hỗ trợ số âm", với liên kết đến dòng chính xác nơi sử dụng throw new Error().

Có lẽ tôi cần làm rõ thêm một chút, vấn đề bạn đang cố giải quyết là gì? Có vẻ như chrome gỡ lỗi kịch bản này tốt. Có lẽ có một số vấn đề với trình gỡ lỗi của Visual Studio.

Hơn nữa

Đây là một bản tái tạo của một trang làm việc có thể được sử dụng từ notepad lưu lại dưới dạng .html

<!DOCTYPE html> 
<html> 
<head> 
<meta http-equiv="content-type" content="text/html; charset=UTF-8"> 
<title>demo</title> 
<script type='text/javascript' src='http://code.jquery.com/jquery-1.6.4.js'></script> 
<script type='text/javascript'>//<![CDATA[ 
$(window).load(function(){ 
$(document).ready(documentReady); 
function documentReady() { 
    $('#btnFactorial').click(btnFactorial_click); 

    factorial(-1); 
} 

function btnFactorial_click() { 
    var x; 
    x = prompt('Enter a number to compute factorial for.', ''); 
    alert(x + '! = ' + factorial(x)); 
} 

function factorial(x) { 
    if (x < 0) 
     throw new Error('factorial function doesn\'t support negative numbers'); 
    else if (x === 0 || x === 1) 
     return 1; 
    else 
     return factorial(x - 1) * x; 
} 
});//]]> 
</script> 
</head> 
<body> 
Factorial Page 
<input type='button' value='Factorial' id='btnFactorial' /> 
</body> 
</html> 

Khi chạy trang này trong google chrome, điều hướng đến tab nguồn khác nhau, và thiết lập một breakpoint tại Line 26: if (x < 0) toàn bộ ngăn xếp cuộc gọi được sao chép khi trang được chạy, ở phía bên tay phải.

factorial (debugpage.html:26) 
documentReady (debugpage.html:16) 
jQuery.extend._Deferred.deferred.resolveWith (jquery-1.6.4.js:1016) 
jQuery.extend._Deferred.deferred.done (jquery-1.6.4.js:1002) 
jQuery.fn.jQuery.ready (jquery-1.6.4.js:282) 
(anonymous function) (debugpage.html:11) 
jQuery.event.handle (jquery-1.6.4.js:3001) 
jQuery.event.add.elemData.handle.eventHandle (jquery-1.6.4.js:2635) 

Thậm chí hơn nữa

Hy vọng rằng bối cảnh này sẽ là tốt nhất được nêu ra. Tìm kiếm một chút vào truy tìm ngăn xếp, tôi thấy điều này: console.trace();. Đó là rất hữu ích.

Chèn nó vào mã trên tại dòng 26 như sau:

if (x < 0) 
    throw new Error('factorial function doesn\'t support negative numbers'); 
else if (x === 0 || x === 1) 

trở thành

if (x < 0){ 
    console.trace(); 
    throw new Error('factorial function doesn\'t support negative numbers'); 
}else if (x === 0 || x === 1) 

Chạy nó bây giờ, mà không một breakpoint, sẽ tạo ra các vết đống trong bảng điều khiển khi điều kiện lỗi được đáp ứng:

console.trace() debugpage.html:27 
factorial debugpage.html:27 
documentReady debugpage.html:16 
jQuery.extend._Deferred.deferred.resolveWith jquery-1.6.4.js:1016 
jQuery.extend._Deferred.deferred.done jquery-1.6.4.js:1002 
jQuery.fn.jQuery.ready jquery-1.6.4.js:282 
(anonymous function) debugpage.html:11 
jQuery.event.handle jquery-1.6.4.js:3001 
jQuery.event.add.elemData.handle.eventHandle 
+0

Cảm ơn câu trả lời chi tiết của bạn. Thật không may, tôi đã hoàn toàn đầm lầy một khi tôi đăng bounty này, vì vậy tôi đã không thể thử điều này. Tôi sẽ trở lại với nó; Tôi hứa! Điều này đã được lái xe cho tôi hạt. –

1

I trie d ví dụ nhỏ của bạn với trình gỡ lỗi IE tích hợp và nó đã báo cáo thông báo ngoại lệ tốt, đặt con trỏ lên ném.

Điều tương tự trong Chrome.

Tôi có jquery v1.6.2. Có thể đáng để nâng cấp?

Sau đó, một lần nữa, điều này có mùi giống như một vấn đề luồng. Nếu nó luôn luôn xảy ra cùng với một cập nhật giao diện người dùng (giống như cảnh báo), nó có thể là trình gỡ lỗi VS đang xem xét một luồng máy chủ UI khi nó nghĩ rằng nó nằm trong chuỗi js. Nói cách khác, một lỗi trong trình gỡ lỗi. Nếu trường hợp này xảy ra, bạn nên thử trình gỡ lỗi khác để xem sự cố có biến mất hay không.

Các vấn đề liên quan