Me gustaría detectar cada error de función indefinido arrojado. ¿Existe una facilidad de manejo de errores global en JavaScript? El caso de uso es capturar llamadas de función desde flash que no están definidas.
Me gustaría detectar cada error de función indefinido arrojado. ¿Existe una facilidad de manejo de errores global en JavaScript? El caso de uso es capturar llamadas de función desde flash que no están definidas.
Respuestas:
¿Esto te ayuda a:
<script type="text/javascript">
window.onerror = function() {
alert("Error caught");
};
xxx();
</script>
Sin embargo, no estoy seguro de cómo maneja los errores de Flash ...
Actualización: no funciona en Opera, pero estoy pirateando Dragonfly en este momento para ver qué obtiene. La sugerencia sobre la piratería de Dragonfly provino de esta pregunta:
window.onerror = function() { alert(42) };
ahora el código en la respuesta: window.onerror = function() { alert("Error caught"); };
no anulado, todavía no estoy seguro ..
Asigne el window.onerror
evento 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 debería suprimir la visualización de un cuadro de diálogo de alerta.
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 capturadas
- 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
Ejemplo del código onerror anterior en acción después de agregar esto a una página de prueba:
<script type="text/javascript">
call_something_undefined();
</script>
var error_data = {
url: document.location.href,
};
if(error != null) {
error_data['name'] = error.name; // e.g. ReferenceError
error_data['message'] = error.line;
error_data['stack'] = error.stack;
} else {
error_data['msg'] = msg;
error_data['filename'] = filename;
error_data['line'] = line;
error_data['col'] = col;
}
var xhr = new XMLHttpRequest();
xhr.open('POST', '/ajax/log_javascript_error');
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onload = function() {
if (xhr.status === 200) {
console.log('JS error logged');
} else if (xhr.status !== 200) {
console.error('Failed to log JS error.');
console.error(xhr);
console.error(xhr.status);
console.error(xhr.responseText);
}
};
xhr.send(JSON.stringify(error_data));
https://jsfiddle.net/nzfvm44d/
throw
se hace manualmente. stackoverflow.com/questions/15036165/…
Si su manejo de errores es muy sofisticado y, por lo tanto, puede arrojar un error en sí mismo, es útil agregar un indicador que indique si ya está en "errorHandling-Mode". 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.
handleError
método.
Pruebe Atatus, que proporciona seguimiento avanzado de errores y monitoreo de usuarios reales para aplicaciones web modernas.
Permítanme explicar cómo obtener stacktraces que estén razonablemente completos en todos los navegadores.
Modern Chrome y Opera son totalmente compatibles con las especificaciones de borrador HTML 5 para ErrorEvent y window.onerror
. En ambos navegadores, puede usar window.onerror
o enlazar correctamente al 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
// 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);
})
Lamentablemente, Firefox, Safari e IE todavía existen y tenemos que apoyarlos también. Como el stacktrace no está disponible window.onerror
, tenemos que trabajar un poco más.
Resulta que lo único que podemos hacer para obtener stacktraces de los errores es envolver todo nuestro código en un try{ }catch(e){ }
bloque y luego mirarlo 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
// sendError(data);
throw e;
}
}
}
return func._wrapped;
};
Esto funciona. Cualquier función que ajuste manualmente tendrá un buen manejo de errores, pero resulta que en realidad podemos hacerlo automáticamente en la mayoría de los casos.
Al cambiar la definición global de addEventListener
para que envuelva automáticamente 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 de addEventListener
ha cambiado. De nuevo, solo tenemos que arreglar esto en el prototype
objeto:
var removeEventListener = window.EventTarget.prototype.removeEventListener;
window.EventTarget.prototype.removeEventListener = function (event, callback, bubble) {
removeEventListener.call(this, event, callback._wrapped || callback, bubble);
}
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 desarrollador web en https://www.atatus.com/ .
http://yourserver.com
) para recibir y almacenar. Si elige atatus.com , no necesita hacer nada. Solo incluye dos líneas de script en tu página.
Parece que window.onerror
no proporciona acceso a todos los errores posibles. Específicamente ignora:
<img>
errores de carga (respuesta> = 400).<script>
errores de carga (respuesta> = 400).window.onerror
de manera desconocida (jquery, angular, etc.).Aquí está el comienzo de un script que detecta muchos de estos errores, para que pueda 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://stackoverflow.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://stackoverflow.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);
}
})();
Se podría usar así:
window.onanyerror = function(entity){
console.log('some error', entity);
};
El script completo tiene una implementación predeterminada que intenta imprimir una versión de "visualización" semi legible de la entidad / error que recibe. Se puede usar 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 métodos en varios navegadores / constructores nativos. Esto puede tener efectos secundarios no deseados. Sin embargo, ha sido útil usar durante el desarrollo, para descubrir dónde se producen 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 puesta en escena para que podamos depurar lo que está sucediendo en Un nivel más profundo. Luego se puede apagar en producción.
Espero que esto ayude.
También se debe preservar la devolución de llamada onerror previamente asociada
<script type="text/javascript">
(function() {
var errorCallback = window.onerror;
window.onerror = function () {
// handle error condition
errorCallback && errorCallback.apply(this, arguments);
};
})();
</script>
Si desea una forma unificada de manejar tanto los errores no detectados como los rechazos de promesas no controlados, puede echar un vistazo a la biblioteca no capturada .
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. rechazo no controlado además de window.onerror.
Recomendaría probar Trackjs .
Es un error al iniciar sesión como un servicio.
Es increíblemente simple de configurar. Simplemente agregue una línea <script> a cada página y listo. 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 puede alojar su 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 pueda rastrear los pasos del usuario que condujeron al error, en lugar de solo una referencia de archivo y número de línea (y tal vez el seguimiento de la pila).
Escuchas 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;
};