¿Cuál es la mejor técnica para detectar TODAS las excepciones lanzadas dentro de JavaScript?
Obviamente, la mejor técnica es usar try ... catch. Pero con devoluciones de llamada ansincrónicas y demás, eso puede ser complicado.
Sé que los navegadores IE y Gecko son compatibles con window.onerror, pero ¿qué pasa con Opera y Safari?
Aquí hay un montón de casos de prueba para los que me gustaría tener una solución central de manejo de excepciones:
// ErrorHandler-Test1
var test = null;
test.arg = 5;
// ErrorHandler-Test2
throw (new Error("Hello"));
// ErrorHandler-Test3
throw "Hello again";
// ErrorHandler-Test4
throw {
myMessage: "stuff",
customProperty: 5,
anArray: [1, 2, 3]
};
// ErrorHandler-Test5
try {
var test2 = null;
test2.arg = 5;
} catch(e) {
ErrorHandler.handleError(e);
}
// ErrorHandler-Test6
try {
throw (new Error("Goodbye"));
} catch(e) {
ErrorHandler.handleError(e);
}
// ErrorHandler-Test7
try {
throw "Goodbye again";
} catch(e) {
ErrorHandler.handleError(e);
}
// ErrorHandler-Test8
try {
throw {
myMessage: "stuff",
customProperty: 5,
anArray: [1, 2, 3]
};
} catch(e) {
ErrorHandler.handleError(e);
}
Si piensa en otros casos de prueba, menciónelos. Varios de estos casos mencionan un método ErrorHandler.handleError. Esta es solo una guía sugerida al usar try ... catch.
javascript
exception
Harley.333
fuente
fuente
window.onerror
falta ha sido un problema desde 2003 , pero parece que finalmente se está resolviendo . Por supuesto, Opera seguirá siendo obstinada.Respuestas:
Si usa una biblioteca como jQuery para asignar todos sus controladores de eventos, puede usar una combinación de
window.onerror
y envolver el código del controlador de eventos jQuery y una función lista con una función de manejo de errores (consulte: Seguimiento de errores de JavaScript: por qué window.onerror no es suficiente ).window.onerror
: detecta todos los errores en IE (y la mayoría de los errores en Firefox), pero no hace nada en Safari y Opera.fuente
onerror
enfoque de manejo normal en Safari + Chrome y parece funcionar correctamente.WebKit (Safari, Chrome, etc.) ahora parece ser compatible
onerror
.Publicación original: Hasta donde yo sé, WebKit / Safari no es compatible con el
onerror
evento. Lo cual es una maldita vergüenza.fuente
En realidad, el enfoque de jquery no es tan malo. Ver:
http://docs.jquery.com/Events/error#fn
y:
$(window).error(function(msg, url, line){ $.post("js_error_log.php", { msg: msg, url: url, line: line }); });
fuente
Capture todas las excepciones con su propio controlador de excepciones y use instanceof.
$("inuput").live({ click : function (event) { try { if (somethingGoesWrong) { throw new MyException(); } } catch (Exception) { new MyExceptionHandler(Exception); } } }); function MyExceptionHandler(Exception) { if (Exception instanceof TypeError || Exception instanceof ReferenceError || Exception instanceof RangeError || Exception instanceof SyntaxError || Exception instanceof URIError ) { throw Exception; // native error } else { // handle exception } }
MyExcetpionHandler arrojará un error nativo ya que no hay un bloque try-catch.
Visite http://www.nczonline.net/blog/2009/03/10/the-art-of-throwing-javascript-errors-part-2/
fuente
try-catch
no siempre es la mejor solución. Por ejemplo, en Chrome 7.0 pierde el buen seguimiento de la pila en la ventana de la consola. Relanzar la excepción no ayuda. No conozco ninguna solución que conserve los rastros de pila y le permita reaccionar en caso de excepción.fuente
Con un poco de trabajo, es posible obtener trazas de pila que estén razonablemente completas en todos los navegadores.
Chrome y Opera modernos (es decir, cualquier cosa basada en el motor de renderizado Blink) son totalmente compatibles con la especificación de borrador HTML 5 para ErrorEvent y
window.onerror
. En ambos navegadores puede utilizarwindow.onerror
o (¡sorprendentemente!) Enlazar correctamente con el evento 'error':// Only Chrome & Opera pass the error object. window.onerror = function (message, file, line, col, error) { console.log(message, "from", error.stack); // You can send data to your server // sendData(data); }; // Only Chrome & Opera have an error attribute on the event. window.addEventListener("error", function (e) { console.log(e.error.message, "from", e.error.stack); // You can send data to your server // sendData(data); })
Desafortunadamente, Firefox, Safari e IE todavía existen y también tenemos que admitirlos. Como el stacktrace no está disponible
window.onerror
, tenemos que trabajar un poco más.Resulta que lo único que podemos hacer para obtener trazos de pila de errores es envolver todo nuestro código en un
try{ }catch(e){ }
bloque y luego mirar e.stack. Podemos hacer el proceso algo más fácil con una función llamada wrap que toma una función y devuelve una nueva función con un buen manejo de errores.function wrap(func) { // Ensure we only wrap the function once. if (!func._wrapped) { func._wrapped = function () { try{ func.apply(this, arguments); } catch(e) { console.log(e.message, "from", e.stack); // You can send data to your server // sendData(data); throw e; } } } return func._wrapped; };
Esto funciona. Cualquier función que ajuste manualmente tendrá un buen manejo de errores.
Puede enviar datos usando la etiqueta de imagen de la siguiente manera
function sendData(data) { var img = newImage(), src = http://yourserver.com/jserror + '&data=' + encodeURIComponent(JSON.stringify(data)); img.crossOrigin = 'anonymous'; img.onload = function success() { console.log('success', data); }; img.onerror = img.onabort = function failure() { console.error('failure', data); }; img.src = src; }
Sin embargo, debe hacer backend para recopilar los datos y front-end para visualizar los datos.
En Atatus , estamos trabajando para solucionar este problema. Más que seguimiento de errores, Atatus proporciona un monitoreo real del usuario.
Descargo de responsabilidad: soy desarrollador web en Atatus.
fuente
Es cierto que con los navegadores modernos, el enganche de window.onerror para errores que burbujean hasta la parte superior junto con la adición de controladores de eventos jQuery para errores Ajax capturará prácticamente todos los objetos Error arrojados en su código de cliente. Si está configurando manualmente un controlador para window.onerror, en los navegadores modernos esto se hace
window.addEventListener('error', callback)
, mientras que en IE8 / 9 debe llamarwindow.attachEvent('onerror', callback)
.Tenga en cuenta que, a continuación, debe considerar el entorno en el que se manejan estos errores y el motivo para hacerlo. Una cosa es detectar tantos errores como sea posible con sus trazas de pila, pero el advenimiento de las modernas herramientas de desarrollo F12 resuelve este caso de uso al implementar y depurar localmente. Los puntos de interrupción, etc., le proporcionarán más datos de los que están disponibles en los controladores, especialmente para los errores lanzados por bibliotecas de terceros que se cargaron desde solicitudes CORS. Debe realizar pasos adicionales para indicar al navegador que proporcione estos datos.
El problema clave es proporcionar estos datos en producción, ya que sus usuarios tienen la garantía de ejecutar una gama de navegadores y versiones mucho más amplia de la que posiblemente pueda probar, y su sitio / aplicación se romperá de formas inesperadas, sin importar cuánto control de calidad arroje. eso.
Para manejar esto, necesita un rastreador de errores de producción que capte todos los errores lanzados en los navegadores de sus usuarios, a medida que usan su código, y los envía a un punto final donde usted puede ver los datos y usarlos para corregir los errores a medida que ocurren. . En Raygun (descargo de responsabilidad: trabajo en Raygun) hemos hecho un gran esfuerzo para brindar una gran experiencia para esto, ya que hay muchas trampas y problemas a considerar que una implementación ingenua no se realizará.
Por ejemplo, es probable que agrupe y minimice sus activos JS, lo que significa que los errores lanzados desde el código minificado tendrán trazas de pila basura con nombres de variables alterados. Para esto, necesita su herramienta de compilación para generar mapas de origen (recomendamos UglifyJS2 para esta parte de la canalización), y su rastreador de errores para aceptarlos y procesarlos, convirtiendo los rastros de pila destrozados en otros legibles por humanos. Raygun hace todo esto de inmediato e incluye un punto final de API para aceptar mapas de origen a medida que los genera su proceso de compilación. Esto es clave, ya que deben mantenerse como no públicos, de lo contrario, cualquiera podría desminificar su código, negando su propósito.
La biblioteca cliente raygun4js también viene con
window.onerror
navegadores modernos y heredados, así como con ganchos de jQuery listos para usar, por lo que para configurar esto solo necesita agregar:<script type="text/javascript" src="//cdn.raygun.io/raygun4js/raygun.min.js" </script> <script> Raygun.init('yourApiKey').attach(); </script>
También hay un montón de funcionalidades integradas, incluida la capacidad de mutar la carga útil del error antes de que se envíe, agregando etiquetas y datos personalizados, metadatos sobre el usuario que vio el error. También elimina la molestia de obtener buenos seguimientos de pila de los scripts CORS de terceros mencionados anteriormente, lo que resuelve el temido 'Error de script' (que no contiene ningún mensaje de error ni seguimiento de pila).
Un tema más crucial es que debido a la gran audiencia en la web, su sitio generará miles de instancias duplicadas de cada error. Un servicio de seguimiento de errores como Raygun tiene la inteligencia de agruparlos en grupos de errores para que no se ahogue en una avalancha de notificaciones y le permite ver cada error real listo para ser reparado.
fuente
También estaba buscando el manejo de errores y el seguimiento de la pila y el registro de las acciones del usuario, esto es lo que encontré, espero que esto también te ayude https://github.com/jefferyto/glitchjs
fuente