Quais são as práticas recomendadas para o tratamento de erros de JavaScript?

137

Eu estou olhando para começar a fazer o meu JavaScript um pouco mais à prova de erro, e estou encontrando muita documentação sobre o uso try, catch, finally, e throw, mas eu não estou encontrando uma tonelada de conselhos de especialistas sobre quando e onde jogar erros.

  • Todo código deve ser envolvido em uma tentativa / captura?
  • Há mais conselhos como esse em que ponto os erros devem ser detectados?
  • Existem desvantagens em gerar erros, em vez de o código falhar silenciosamente na produção?
  • Isso foi abordado no SO em relação às implementações, mas os erros de JS do log do servidor são uma estratégia eficaz?
  • Mais alguma coisa que eu deveria saber sobre erros de interceptação no meu aplicativo?

Também sou um jogo completo para ouvir livros que têm ótimos capítulos ou explicações detalhadas sobre como lidar com erros. O JavaScript eloquente aborda o assunto, mas não é muito prescritivo ou opinativo sobre o assunto.

Agradeço qualquer conselho que você possa dar!

Joshua Cody
fonte
Certamente depende de quão espetacularmente você falha se algo der errado e do volume de possíveis mensagens de erro. Você não deseja falhar porque seu diretório de log de erros está cheio agora, não é? - Você olhou aqui? stackoverflow.com/search?q=error+logging+javascript
mplungjan
@mplungjan - Examinei as respostas lá, mas muitas não pareciam canônicas, e as melhores práticas de manipulação / exceção de erros de Javascript não resultaram em nada, então achei que poderia ser útil tentar solicitar algumas ideias condensadas, tanto para os meus própria compreensão e futuros pesquisadores. Talvez este seja um tópico em que a prescrição de melhores práticas não seja tão possível, mas cada situação é altamente única.
Joshua Cody
1
"Todo código deve ser envolvido em uma tentativa / captura?" Claro que não. Você sabe que há muito código que sempre funcionará (supondo que você o teste, é claro, mas o ponto de tentativa / captura não é capturar ou encobrir erros de codificação). Quebra de código apenas que pode falhar algumas vezes devido a algo fora de seu controle, geralmente coisas como acesso a recursos, etc. existem várias bibliotecas que lidam com problemas entre navegadores e permitem especificar uma função de tratamento de erros.
Nnnnnn 27/06
1
Esta é uma boa pergunta Josh, +1. Existem muitos conselhos sintáticos por aí, mas como você diz, essa é a parte mais fácil. Ele é abordado na resposta desta pergunta ( stackoverflow.com/questions/2825427/… ), onde é explicado que as exceções não são tão comumente usadas no JS e as razões são fornecidas.
whitneyland

Respostas:

63

Um conjunto imensamente interessante de slides no Enterprise JavaScript Error Handling pode ser encontrado em http://www.devhands.com/2008/10/javascript-error-handling-and-general-best-practices/

Em resumo, resume:

  1. Suponha que seu código falhe
  2. Erros de log no servidor
  3. Você, não o navegador, lida com erros
  4. Identifique onde os erros podem ocorrer
  5. Jogue seus próprios erros
  6. Distinguir erros fatais versus erros não fatais
  7. Fornecer um modo de depuração

Os slides entram em muito mais detalhes e provavelmente darão alguma orientação.

ATUALIZAR

A apresentação mencionada acima pode ser encontrada aqui: http://www.slideshare.net/nzakas/enterprise-javascript-error-handling-presentation

cdmdotnet
fonte
24
O link devhands está quebrado.
Ryan Gates
7
Para aqueles que leram isso em 2017, eu argumentaria que você não obterá muito valor dos slides - este resumo fornece 90% das informações. Ainda é uma informação valiosa. Felicidades!
Philippe Hebert
29

Nicholas Zakas, do Yahoo! fama fez uma palestra sobre Manipulação de Erros Corporativos ( slides ) no Ajax Experience 2008, na qual ele propôs algo assim:

function log(sev,msg) {
    var img = new Image();
    img.src = "log.php?sev=" +
        encodeURIComponent(sev) +
        "&msg=" + encodeURIComponent(msg);
}

// usage
log(1, "Something bad happened.")

// Auto-log uncaught JS errors
window.onerror = function(msg, url, line) {
    log(1, msg);
    return true;
}

Um ano depois, Nicholas Zakas postou uma atualização em seu blog, que incluía um padrão inteligente para injetar código de tratamento de erros automaticamente em seu ambiente de produção (usando programação orientada a aspectos).

Quando você começa a registrar as chamadas window.error, notará duas coisas:

  1. Se o seu site for bastante complexo, você registrará muitos erros
  2. Você verá várias mensagens "window.error" inúteis em undefined: 0 "

Reduzir o torrent de entradas de log é tão simples quanto testar a gravidade e / ou um número aleatório antes de efetuar o logon no servidor:

function log(sev,msg) {
    if (Math.random() > 0.1) return; // only log some errors

    var img = new Image();
    img.src = "log.php?sev=" +
        encodeURIComponent(sev) +
        "&msg=" + encodeURIComponent(msg);
}

O tratamento dos erros inúteis "window.error em undefined: 0" depende da arquitetura do site, mas pode tentar identificar todas as chamadas do Ajax e gerar uma exceção quando algo falhar (possivelmente retornando um rastreamento de pilha usando o stacktrace.js ).

Jens Roland
fonte
67
Sei que essa é uma pergunta antiga, mas sugerir ignorar alguns erros aleatoriamente é uma das piores idéias que já ouvi.
Jbabey
26
@jbabey: Para um site pequeno, você está certo, mas se você estiver executando um site grande com 100.000 milhões ou milhões de usuários, não precisará realmente inundar seus servidores (ou a Internet) com solicitações de registro redundantes. Em um sistema grande o suficiente, todos os erros reais ocorrem dezenas de milhares de vezes por dia, portanto, essa forma de limitação funciona perfeitamente. A ideia é realmente implementada no Facebook.
Jens Roland
1
Erros de log no modo de depuração provavelmente são tão importantes quanto a limitação de relatórios de erros de produção; portanto, é possível notar que é necessária uma solução para gerenciar esse valor, limitando o limite de log.
Frattaro 02/10/2015
2
O @NickBull fiz a engenharia reversa de vários módulos JavaScript do Facebook em 2011-2012; foi onde eu encontrei.
Jens Roland
1
@ NickBull acabou de verificar meus arquivos antigos, ainda os tinha. Eu encontrei este truque no módulo bootloader Facebook: if (global.logJSError) if (Math.random() < .01) logJSError('bootloader', {(reconhecidamente que o código não acelerador todos os erros, apenas uma classe específica de erros de tempo limite)
Jens Roland
7

IHMO, você deve usar o tratamento de erros em javascript como em várias outras línguas (AFAIK: Python, Java).

Para melhor legibilidade (e provavelmente melhor desempenho, mesmo que eu não tenha certeza de que tenha um impacto muito grande), você deve usar o bloco try / catch principalmente nos seguintes casos:

  • A parte do código que você deseja quebrar é uma parte essencial de todo o algoritmo . Se falhar, poderá:

    • crie erros na próxima parte dos códigos (por exemplo, porque um var está ausente ...)
    • faça com que a página não tenha a aparência esperada (impacto no conteúdo ou no css)
    • fazer com que os resultados pareçam estranhos para o usuário (impacto no comportamento do código)
  • Você sabe que o código que está escrevendo não é compatível com todos os navegadores

  • Você planejou que o código falhe (porque não há outra maneira de verificar se ele deve funcionar se ... então ... bloqueia)
  • E também quando você deseja depurar sem incomodar o usuário final

Eventualmente, os especialistas em javascript podem ter outros elementos para fornecer.

meus 2 centavos para a caixa,

Saudações,

Máx.

JMax
fonte
1
"A parte do código que você deseja quebrar é uma parte essencial de todo o algoritmo" - pode depender de como você deseja lidar com a falha. Se você sabe que não há como continuar com o algoritmo após a falha, pode ser melhor agrupar tudo em uma tentativa / captura, porque se a sua tentativa / captura estiver (por exemplo) enterrada em loops aninhados, será mais um impacto no desempenho . Por outro lado, se você puder executar alguma ação com exceção e continuar com o algoritmo, precisará de uma configuração de tentativa / captura mais refinada.
Nnnnnn 27/06
5

Além das outras respostas: uma coisa importante é usar os dados de contexto disponíveis nos objetos de erro do JavaScript e nos window.onerrorparâmetros da função.

Coisas como o rastreamento de pilha (errorObject.stack), o nome do arquivo, o número da linha e o número da coluna. Observe que cada navegador tem algumas diferenças ... então faça o seu melhor para obter bons erros.

Pode até haver problemas com o próprio objeto do console . Eu uso uma função window.onerror personalizada inspirada neste e uma função especial para rastrear qualquer objeto de erro padrão inspirado nesse código .

Outro ponto positivo é incluir a versão do seu aplicativo da Web em algum lugar próximo ao rastreamento de pilha (para copiar e colar de maneira rápida e segura). Você também pode mostrar erros de forma mais agressiva (alerta ...) no modo de desenvolvimento, pois os desenvolvedores não monitoram constantemente o console do navegador e podem não ver alguns dos problemas.

Além disso, use evitar usar throw 'My message', usar throw new Error('My message'), você pode até ter erros personalizados, leia este artigo .

Sempre adicione algum contexto aos erros (a versão, o ID do objeto, alguma mensagem personalizada ...) e também faça uma distinção entre erros externos (alguns dados ou circunstâncias externas causaram falha no sistema) e erros internos / assertions (seu próprio sistema está estragado), leia sobre ' Design by contract '.

Aqui está um guia .

Pense também em usar o tratamento geral de erros, como interceptadores de suas bibliotecas e estruturas:

Christophe Roussy
fonte