2012-05-08 12 views
12

Tengo un problema al depurar mis aplicaciones web. Es muy frustrante porque he intentado reproducir el problema con una pequeña página web que puedo publicar en jsfiddle, pero este parece ser un caso del "Higgs-Bugson".La pila de llamadas se pierde cuando se lanza una excepción dentro de un manejador de jQuery

Tengo una página web con un controlador grande jQuery(document).ready(). El problema es que cuando se lanza una excepción desde el controlador jQuery(document).ready(), obtengo una pila de llamadas con varias funciones anónimas y sin un puntero al código que arrojó la excepción.

Siempre que intente reproducir este comportamiento con una pequeña página web, siempreobtener un puntero al código que lanzó la excepción, pero en el código de producción, nuncaconsigo el puntero de pila. Esto hace que la depuración sea más frustrante y propensa a errores.

¿Alguien aquí tiene alguna idea de qué podría estar causando este comportamiento y cómo hacerlo bien?


Actualización: Ya han pasado varios meses desde que he publicado esta pregunta y ahora creo que he reproducido de manera concluyente el tema. Reproduzco el tema con el código HTML siguiente:

<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> 

Si examina el código, verá que cuando hace clic en un botón, el código de alerta al factorial de un número que especifique. Ingrese un número negativo y se producirá un error. En este caso, Visual Studio detectará el error y resaltará la línea de código donde ocurrió el error y mostrará una pila de llamadas que incluye factorial y btnFactorial_click.

Este código también invoca factorial(-1) del controlador $ (documento) .ready. En este caso, Visual Studio mueve el cursor sobre el bloque finally en el siguiente código de jQuery (extraído de jquery-1.6.1.js, comienza en la línea 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; 
      }, 

Aunque no se muestra la pila de llamadas, Visual Studio muestra una ventana emergente que muestra el texto del error

¿Cuál es la razón de este comportamiento extraño y cómo puedo diseñar mi aplicación para que pueda atrapar fácilmente los errores que se originan en controladores como $ (documento) .ready ?

+5

+1 para Higgs-Bugson –

+0

¿Podría publicar un ejemplo de código? – izb

+0

@izb, el problema siempre aparece en mi código de producción (que no puedo publicar aquí), pero nunca aparece en el código de prueba que escribo para intentar aislar el problema. –

Respuesta

2

Sugeriría crear un objeto que se crea una instancia dentro del bloque jQuery(document).ready(). Por ejemplo:

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

oStart.init(); 

Esto le ayudará a separar la lógica de su aplicación y la lógica jQuery. Deberías tener muy poco en tu bloque listo. Solo aquellas cosas que son absolutamente necesarias después de que DOM se haya cargado completamente. Todo lo demás debería poder cargarse en la memoria mientras la página está todavía renderizando.

+0

Este código no se ha probado y se publicó para explicar la idea, no el código de producción. : D – seangates

4

I'm having a problem debugging my web applications

¿Qué tipo de depurador está usando? Tienden a variar y el mejor que he encontrado al desarrollar es el de Firefox debido a algunas herramientas integradas muy bonitas que tienen.

Aunque es bueno reproducir un problema, cuando no se puede reproducir en un simple ejemplo sucinto, la depuración se vuelve cada vez más importante.Establecer puntos de interrupción y avanzar línea por línea a veces es la única manera en lugar de esperar a que ocurra el error durante el tiempo de ejecución y luego volver a rastrear.

Existen varios enfoques descritos en este artículo de MSDN que podrían ser útiles para ayudar a resolver su problema. Estoy seguro de que has probado algunos de ellos, pero al menos vale la pena mirarlo, especialmente "Escenario 3: estoy recibiendo un error en el fondo de un conjunto de métodos de ayuda, y no estoy seguro de dónde se originó el error".

"Cómo depurar el código de jQuery"

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

Editar en respuesta a nuevos contenidos

jsFiddle de nuevos contenidos: http://jsfiddle.net/EJbsS/

Cuando se ejecuta el jsFiddle en cromo, se llama a la primera pasada por factorial (-1). Aparece un error Se puede acceder haciendo clic en la parte inferior derecha de la x roja, o inspeccionando el elemento, navegando a la pestaña de la consola y luego mirando el área de texto. El error dice "Error no detectado: la función factorial no admite números negativos", con un enlace a la línea exacta donde se usa throw new Error().

Quizás necesite un poco más de aclaración, ¿cuál es el problema que está tratando de resolver? Parece que Chrome depura este script muy bien. Quizás haya algunos problemas con el depurador de Visual Studio.

Además

Aquí es una reproducción de una página de trabajo que se puede utilizar desde el bloc de notas guardado como .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> 

Cuando se ejecuta esta página en Google Chrome, navegando a la pestaña fuentes, y estableciendo un punto de interrupción en Line 26: if (x < 0), la pila de llamadas completa se reproduce cuando se ejecuta la página, en el lado derecho.

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) 

Aún más

Con suerte esta advertencia será el mejor hasta ahora. Buscando un poco en el seguimiento de la pila, encontré esto: console.trace();. Es muy útil.

insertarlo en el código anterior en la línea 26, así:

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

Se convierte en

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

Correr ahora, sin un punto de ruptura, se producirá el seguimiento de la pila en la consola cuando la condición de error se cumple:

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

Gracias por su respuesta detallada. Desafortunadamente, quedé absolutamente abrumado una vez que publiqué esta recompensa, así que no he podido probar esto. Regresaré a eso; ¡Lo prometo! Esto me ha estado volviendo loco. –

1

I trie d su pequeño ejemplo con el depurador de IE incorporado e informó el mensaje de excepción simplemente, colocando el cursor en el tiro.

Lo mismo en Chrome.

Tengo jquery v1.6.2. Tal vez vale la pena una actualización?

Por otra parte, esto huele como un problema de enhebrado. Si siempre ocurre junto con una actualización de UI (como la alerta), podría ser que el depurador VS esté mirando un hilo del servidor de la interfaz de usuario cuando cree que está en el hilo js. En otras palabras, un error en el depurador. Si este es el caso, debería probar un depurador diferente para ver si el problema desaparece.

Cuestiones relacionadas