solucionar como change javascript javascript-events

como - Manejo de errores global de JavaScript



javascript void 0 como solucionar (10)

Me gustaría capturar cada error de función indefinido lanzado. ¿Hay una facilidad de manejo de errores global en JavaScript? El caso de uso es la captura de llamadas de función desde flash que no están definidas.


Cómo atrapar errores de Javascript no manejados

Asigne el evento window.onerror a un controlador de eventos como:

<script type="text/javascript"> window.onerror = function(msg, url, line, col, error) { // Note that col & error are new to the HTML 5 spec and may not be // supported in every browser. It worked for me in Chrome. var extra = !col ? '''' : ''/ncolumn: '' + col; extra += !error ? '''' : ''/nerror: '' + error; // You can view the information in an alert to see things working like this: alert("Error: " + msg + "/nurl: " + url + "/nline: " + line + extra); // TODO: Report this error via ajax so you can keep track // of what pages have JS issues var suppressErrorAlert = true; // If you return true, then error alerts (like in older versions of // Internet Explorer) will be suppressed. return suppressErrorAlert; }; </script>

Como se comentó en el código, si el valor de retorno de window.onerror es true entonces el navegador debe suprimir el cuadro de diálogo de alerta.

¿Cuándo se activa el evento window.onerror?

En pocas palabras, el evento se genera cuando: 1.) hay una excepción no detectada o 2.) se produce un error de tiempo de compilación.

excepciones no detectadas

  • lanzar "algunos mensajes"
  • call_something_undefined ();
  • cross_origin_iframe.contentWindow.document ;, una excepción de seguridad

Error de compilación

  • <script>{</script>
  • <script>for(;)</script>
  • <script>"oops</script>
  • setTimeout("{", 10); , intentará compilar el primer argumento como un script

Los navegadores soportan window.onerror

  • Chrome 13+
  • Firefox 6.0+
  • Internet Explorer 5.5+
  • Opera 11.60+
  • Safari 5.1+

Captura de pantalla:

Ejemplo del código de error anterior en acción después de agregar esto a una página de prueba:

<script type="text/javascript"> call_something_undefined(); </script>

JSFiddle:

https://jsfiddle.net/nzfvm44d/

Referencias:


manejo sofisticado de errores

Si su manejo de errores es muy sofisticado y, por lo tanto, puede generar un error en sí mismo, es útil agregar una marca que indique si ya se encuentra en el "Modo de manejo de errores". Al igual que:

var appIsHandlingError = false; window.onerror = function() { if (!appIsHandlingError) { appIsHandlingError = true; handleError(); } }; function handleError() { // graceful error handling // if successful: appIsHandlingError = false; }

De lo contrario, podría encontrarse en un bucle infinito.


¿Te ayuda esto?

<script type="text/javascript"> window.onerror = function() { alert("Error caught"); }; xxx(); </script>

No estoy seguro de cómo maneja los errores de Flash aunque ...

Actualización: no funciona en Opera, pero estoy hackeando Dragonfly ahora mismo para ver qué se obtiene. La sugerencia sobre hackear Dragonfly vino de esta pregunta:

Ventana mímica. onerror en Opera usando javascript


Parece que window.onerror no proporciona acceso a todos los errores posibles. Específicamente se ignora:

  1. <img> errores de carga (respuesta> = 400).
  2. <script> errores de carga (respuesta> = 400).
  3. errores globales si tiene muchas otras bibliotecas en su aplicación que también manipulan window.onerror de una forma desconocida (jquery, angular, etc.).
  4. probablemente muchos casos no he encontrado después de explorar esto ahora (iframes, desbordamiento de pila, etc.).

Aquí está el inicio de un script que captura muchos de estos errores, de modo que puede agregar una depuración más sólida a su aplicación durante el desarrollo.

(function(){ /** * Capture error data for debugging in web console. */ var captures = []; /** * Wait until `window.onload`, so any external scripts * you might load have a chance to set their own error handlers, * which we don''t want to override. */ window.addEventListener(''load'', onload); /** * Custom global function to standardize * window.onerror so it works like you''d think. * * @see http://www.quirksmode.org/dom/events/error.html */ window.onanyerror = window.onanyerror || onanyerrorx; /** * Hook up all error handlers after window loads. */ function onload() { handleGlobal(); handleXMLHttp(); handleImage(); handleScript(); handleEvents(); } /** * Handle global window events. */ function handleGlobal() { var onerrorx = window.onerror; window.addEventListener(''error'', onerror); function onerror(msg, url, line, col, error) { window.onanyerror.apply(this, arguments); if (onerrorx) return onerrorx.apply(null, arguments); } } /** * Handle ajax request errors. */ function handleXMLHttp() { var sendx = XMLHttpRequest.prototype.send; window.XMLHttpRequest.prototype.send = function(){ handleAsync(this); return sendx.apply(this, arguments); }; } /** * Handle image errors. */ function handleImage() { var ImageOriginal = window.Image; window.Image = ImageOverride; /** * New `Image` constructor. Might cause some problems, * but not sure yet. This is at least a start, and works on chrome. */ function ImageOverride() { var img = new ImageOriginal; onnext(function(){ handleAsync(img); }); return img; } } /** * Handle script errors. */ function handleScript() { var HTMLScriptElementOriginal = window.HTMLScriptElement; window.HTMLScriptElement = HTMLScriptElementOverride; /** * New `HTMLScriptElement` constructor. * * Allows us to globally override onload. * Not ideal to override stuff, but it helps with debugging. */ function HTMLScriptElementOverride() { var script = new HTMLScriptElement; onnext(function(){ handleAsync(script); }); return script; } } /** * Handle errors in events. * * @see http://.com/questions/951791/javascript-global-error-handling/31750604#31750604 */ function handleEvents() { var addEventListenerx = window.EventTarget.prototype.addEventListener; window.EventTarget.prototype.addEventListener = addEventListener; var removeEventListenerx = window.EventTarget.prototype.removeEventListener; window.EventTarget.prototype.removeEventListener = removeEventListener; function addEventListener(event, handler, bubble) { var handlerx = wrap(handler); return addEventListenerx.call(this, event, handlerx, bubble); } function removeEventListener(event, handler, bubble) { handler = handler._witherror || handler; removeEventListenerx.call(this, event, handler, bubble); } function wrap(fn) { fn._witherror = witherror; function witherror() { try { fn.apply(this, arguments); } catch(e) { window.onanyerror.apply(this, e); throw e; } } return fn; } } /** * Handle image/ajax request errors generically. */ function handleAsync(obj) { var onerrorx = obj.onerror; obj.onerror = onerror; var onabortx = obj.onabort; obj.onabort = onabort; var onloadx = obj.onload; obj.onload = onload; /** * Handle `onerror`. */ function onerror(error) { window.onanyerror.call(this, error); if (onerrorx) return onerrorx.apply(this, arguments); }; /** * Handle `onabort`. */ function onabort(error) { window.onanyerror.call(this, error); if (onabortx) return onabortx.apply(this, arguments); }; /** * Handle `onload`. * * For images, you can get a 403 response error, * but this isn''t triggered as a global on error. * This sort of standardizes it. * * "there is no way to get the HTTP status from a * request made by an img tag in JavaScript." * @see http://.com/questions/8108636/how-to-get-http-status-code-of-img-tags/8108646#8108646 */ function onload(request) { if (request.status && request.status >= 400) { window.onanyerror.call(this, request); } if (onloadx) return onloadx.apply(this, arguments); } } /** * Generic error handler. * * This shows the basic implementation, * which you could override in your app. */ function onanyerrorx(entity) { var display = entity; // ajax request if (entity instanceof XMLHttpRequest) { // 400: http://example.com/image.png display = entity.status + '' '' + entity.responseURL; } else if (entity instanceof Event) { // global window events, or image events var target = entity.currentTarget; display = target; } else { // not sure if there are others } capture(entity); console.log(''[onanyerror]'', display, entity); } /** * Capture stuff for debugging purposes. * * Keep them in memory so you can reference them * in the chrome debugger as `onanyerror0` up to `onanyerror99`. */ function capture(entity) { captures.push(entity); if (captures.length > 100) captures.unshift(); // keep the last ones around var i = captures.length; while (--i) { var x = captures[i]; window[''onanyerror'' + i] = x; } } /** * Wait til next code execution cycle as fast as possible. */ function onnext(fn) { setTimeout(fn, 0); } })();

Podría ser usado así:

window.onanyerror = function(entity){ console.log(''some error'', entity); };

El script completo tiene una implementación predeterminada que intenta imprimir una versión "visualizable" de la entidad / error que recibe. Puede usarse como inspiración para un controlador de errores específico de la aplicación. La implementación predeterminada también mantiene una referencia a las últimas 100 entidades de error, por lo que puede inspeccionarlas en la consola web después de que ocurran, como:

window.onanyerror0 window.onanyerror1 ... window.onanyerror99

Nota: Esto funciona anulando los métodos en varios navegadores / constructores nativos. Esto puede tener efectos secundarios no deseados. Sin embargo, ha sido útil usarlo durante el desarrollo, para averiguar dónde ocurren los errores, para enviar registros a servicios como NewRelic o Sentry durante el desarrollo para que podamos medir los errores durante el desarrollo, y en la preparación para poder depurar lo que sucede en un nivel más profundo. Entonces se puede apagar en producción.

Espero que esto ayude.


Pruebe Atatus que proporciona seguimiento de errores avanzado y monitoreo real del usuario para aplicaciones web modernas.

Atatus

Permítame explicarle cómo obtener stacktraces que estén razonablemente completos en todos los navegadores.

Manejo de errores en JavaScript

Modern Chrome y Opera son totalmente compatibles con las especificaciones de borrador HTML 5 para ErrorEvent y window.onerror . En ambos de estos navegadores, puede usar window.onerror o enlazar al evento ''error'' correctamente:

// 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 // sendError(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 // sendError(data); })

Desafortunadamente, Firefox, Safari e IE todavía existen y tenemos que apoyarlos también. Como el stacktrace no está disponible en window.onerror , tenemos que hacer un poco más de trabajo.

Resulta que lo único que podemos hacer para obtener los stacktres de los errores es envolver todo nuestro código en un bloque try{ }catch(e){ } y luego ver e.stack . Podemos hacer que el proceso sea más fácil con una función llamada ajuste 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 // sendError(data); throw e; } } } return func._wrapped; };

Esto funciona. Cualquier función que ajuste manualmente tendrá un buen manejo de errores, pero resulta que podemos hacerlo automáticamente en la mayoría de los casos.

Al cambiar la definición global de addEventListener para que automáticamente ajuste la devolución de llamada, podemos insertar automáticamente try{ }catch(e){ } alrededor de la mayoría del código. Esto permite que el código existente continúe funcionando, pero agrega un seguimiento de excepciones de alta calidad.

var addEventListener = window.EventTarget.prototype.addEventListener; window.EventTarget.prototype.addEventListener = function (event, callback, bubble) { addEventListener.call(this, event, wrap(callback), bubble); }

También debemos asegurarnos de que removeEventListener siga funcionando. Por el momento no lo hará porque el argumento para addEventListener ha cambiado. Nuevamente solo necesitamos arreglar esto en el objeto prototype :

var removeEventListener = window.EventTarget.prototype.removeEventListener; window.EventTarget.prototype.removeEventListener = function (event, callback, bubble) { removeEventListener.call(this, event, callback._wrapped || callback, bubble); }

Transmitir datos de error a su backend

Puede enviar datos de error utilizando la etiqueta de imagen de la siguiente manera

function sendError(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; }

Descargo de responsabilidad: soy un desarrollador web en Atatus .


Recomendaría darle una oportunidad a Trackjs .

Es el registro de errores como un servicio.

Es increíblemente sencillo de configurar. Solo agrega una línea <script> a cada página y eso es todo. Esto también significa que será increíblemente fácil de eliminar si decides que no te gusta.

Hay otros servicios como Sentry (que es de código abierto si puedes alojar tu propio servidor), pero no hace lo que hace Trackjs. Trackjs registra la interacción del usuario entre su navegador y su servidor web para que realmente pueda rastrear los pasos del usuario que llevaron al error, en lugar de solo una referencia de número de línea y archivo (y tal vez un seguimiento de la pila).


Si desea una forma unificada de manejar tanto los errores no detectados como los rechazos de promesa no manejados, puede echar un vistazo a la biblioteca no detectada .

EDITAR

<script type="text/javascript" src=".../uncaught/lib/index.js"></script> <script type="text/javascript"> uncaught.start(); uncaught.addListener(function (error) { console.log(''Uncaught error or rejection: '', error.message); }); </script>

Escucha ventana. unhandledrejection además de window.onerror.


Uno debe preservar el callback onerror previamente asociado también

<script type="text/javascript"> (function() { var errorCallback = window.onerror; window.onerror = function () { // handle error condition errorCallback && errorCallback.apply(this, arguments); }; })(); </script>


Usted escucha el evento onerror asignando una función a window.onerror:

window.onerror = function (msg, url, lineNo, columnNo, error) { var string = msg.toLowerCase(); var substring = "script error"; if (string.indexOf(substring) > -1){ alert(''Script Error: See Browser Console for Detail''); } else { alert(msg, url, lineNo, columnNo, error); } return false; };


// display error messages for a page, but never more than 3 errors window.onerror = function(msg, url, line) { if (onerror.num++ < onerror.max) { alert("ERROR: " + msg + "/n" + url + ":" + line); return true; } } onerror.max = 3; onerror.num = 0;