Eu gostaria de pegar todos os erros de função indefinidos lançados. Existe um recurso global de tratamento de erros em JavaScript? O caso de uso está capturando chamadas de função do flash que não estão definidas.
Eu gostaria de pegar todos os erros de função indefinidos lançados. Existe um recurso global de tratamento de erros em JavaScript? O caso de uso está capturando chamadas de função do flash que não estão definidas.
Respostas:
Isso ajuda você a:
<script type="text/javascript">
window.onerror = function() {
alert("Error caught");
};
xxx();
</script>
Não tenho certeza de como ele lida com erros do Flash ...
Atualização: não funciona no Opera, mas estou hackeando o Dragonfly agora para ver o que acontece. A sugestão sobre hackers Dragonfly veio desta pergunta:
window.onerror = function() { alert(42) };
agora o código na resposta: window.onerror = function() { alert("Error caught"); };
não anulado, eu ainda não tenho certeza ..
Atribua o window.onerror
evento a um manipulador 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>
Conforme comentado no código, se o valor de retorno window.onerror
for for true
, o navegador deverá suprimir a exibição de uma caixa de diálogo de alerta.
Em poucas palavras, o evento é gerado quando 1.) há uma exceção não capturada ou 2.) ocorre um erro no tempo de compilação.
exceções não capturadas
- jogue "algumas mensagens"
- call_something_undefined ();
- cross_origin_iframe.contentWindow.document ;, uma exceção de segurança
erro de compilação
<script>{</script>
<script>for(;)</script>
<script>"oops</script>
setTimeout("{", 10);
, ele tentará compilar o primeiro argumento como um script
Exemplo do código onerror acima em ação depois de adicioná-lo a uma página de teste:
<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
é feita manualmente. stackoverflow.com/questions/15036165/…
Se o tratamento de erros for muito sofisticado e, portanto, puder gerar um erro, é útil adicionar um sinalizador indicando se você já está no "errorHandling-Mode". Igual a:
var appIsHandlingError = false;
window.onerror = function() {
if (!appIsHandlingError) {
appIsHandlingError = true;
handleError();
}
};
function handleError() {
// graceful error handling
// if successful: appIsHandlingError = false;
}
Caso contrário, você poderá se encontrar em um loop infinito.
handleError
método.
Experimente o Atatus, que fornece rastreamento avançado de erros e monitoramento real de usuários para aplicativos da web modernos.
Deixe-me explicar como obter rastreamentos de pilha razoavelmente completos em todos os navegadores.
O Chrome e o Opera modernos são totalmente compatíveis com as especificações de rascunho do HTML 5 para ErrorEvent e window.onerror
. Nos dois navegadores, você pode usar window.onerror
ou vincular o evento 'error' corretamente:
// 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);
})
Infelizmente, o Firefox, o Safari e o IE ainda estão por aí e também precisamos apoiá-los. Como o stacktrace não está disponível window.onerror
, precisamos trabalhar um pouco mais.
Acontece que a única coisa que podemos fazer para obter rastreamentos de pilha de erros é agrupar todo o nosso código em um try{ }catch(e){ }
bloco e depois examinar e.stack
. Podemos tornar o processo um pouco mais fácil com uma função chamada wrap que pega uma função e retorna uma nova função com boa manipulação de erros.
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;
};
Isso funciona. Qualquer função que você agrupar manualmente terá um bom tratamento de erros, mas na verdade podemos fazer isso automaticamente na maioria dos casos.
Alterando a definição global de addEventListener
para que ele agrupe automaticamente o retorno de chamada, podemos inserir automaticamente a try{ }catch(e){ }
maioria dos códigos. Isso permite que o código existente continue a funcionar, mas adiciona o rastreamento de exceções de alta qualidade.
var addEventListener = window.EventTarget.prototype.addEventListener;
window.EventTarget.prototype.addEventListener = function (event, callback, bubble) {
addEventListener.call(this, event, wrap(callback), bubble);
}
Também precisamos garantir que isso removeEventListener
continue funcionando. No momento, não será porque o argumento para addEventListener
foi alterado. Novamente, só precisamos consertar isso no prototype
objeto:
var removeEventListener = window.EventTarget.prototype.removeEventListener;
window.EventTarget.prototype.removeEventListener = function (event, callback, bubble) {
removeEventListener.call(this, event, callback._wrapped || callback, bubble);
}
Você pode enviar dados de erro usando a tag de imagem da seguinte maneira
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;
}
Isenção de responsabilidade: Sou desenvolvedor da Web em https://www.atatus.com/ .
http://yourserver.com
) para receber e armazenar. Se você escolher atatus.com , não precisará fazer nada. Basta incluir duas linhas de script em sua página.
Parece que window.onerror
não fornece acesso a todos os erros possíveis. Ignora especificamente:
<img>
erros de carregamento (resposta> = 400).<script>
erros de carregamento (resposta> = 400).window.onerror
maneira desconhecida (jquery, angular etc.).Aqui está o início de um script que captura muitos desses erros, para que você possa adicionar uma depuração mais robusta ao seu aplicativo durante o desenvolvimento.
(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);
}
})();
Pode ser usado assim:
window.onanyerror = function(entity){
console.log('some error', entity);
};
O script completo possui uma implementação padrão que tenta imprimir uma versão "display" semi-legível da entidade / erro que ele recebe. Pode ser usado como inspiração para um manipulador de erros específico do aplicativo. A implementação padrão também mantém uma referência às 100 últimas entidades de erro, para que você possa inspecioná-las no console da Web após elas ocorrerem como:
window.onanyerror0
window.onanyerror1
...
window.onanyerror99
Nota: Isso funciona substituindo métodos em vários navegadores / construtores nativos. Isso pode ter efeitos colaterais não intencionais. No entanto, tem sido útil usá-lo durante o desenvolvimento, descobrir onde os erros estão ocorrendo, enviar logs para serviços como NewRelic ou Sentry durante o desenvolvimento para que possamos medir erros durante o desenvolvimento e na preparação para que possamos depurar o que está acontecendo em um nível mais profundo. Em seguida, ele pode ser desativado na produção.
Espero que isto ajude.
Deve-se preservar também o retorno de chamada onerror associado anteriormente
<script type="text/javascript">
(function() {
var errorCallback = window.onerror;
window.onerror = function () {
// handle error condition
errorCallback && errorCallback.apply(this, arguments);
};
})();
</script>
Se você deseja uma maneira unificada de lidar com erros não capturados e rejeições de promessa não tratadas, consulte a biblioteca não 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>
Ouve janela. rejeição não tratada além de window.onerror.
Eu recomendaria experimentar o Trackjs .
É log de erro como um serviço.
É incrivelmente simples de configurar. Basta adicionar uma linha <script> a cada página e pronto. Isso também significa que será incrivelmente simples de remover se você decidir que não gosta.
Existem outros serviços como o Sentry (que é de código aberto se você pode hospedar seu próprio servidor), mas não faz o que o Trackjs faz. O Trackjs registra a interação do usuário entre o navegador e o servidor da web, para que você possa rastrear as etapas do usuário que levaram ao erro, em vez de apenas uma referência de arquivo e número de linha (e talvez rastreamento de pilha).
Você ouve o evento onerror atribuindo uma função 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;
};