o que é um erro na programação?
as coisas nem sempre correm bem nos nossos Programas.
em particular, existem situações em que podemos querer parar o programa ou informar o Usuário se algo ruim acontecer.
Por exemplo:
- o programa tentou abrir um ficheiro inexistente.a ligação à rede está avariada.
- o utilizador introduziu dados inválidos.,
em todos estes casos nós, como programadores, criamos erros, ou deixamos o motor de programação criar alguns para nós.
Depois de criar o erro podemos informar o usuário com uma mensagem, ou podemos parar a execução completamente.
o que é um erro em JavaScript?
um erro em JavaScript é um objeto, que é posteriormente jogado para parar o programa.
para criar um novo erro no JavaScript chamamos a função de construtor apropriada., Por exemplo, para criar um novo erro genérico que nós podemos fazer:
const err = new Error("Something bad happened!");
Ao criar um objeto de erro também é possível omitir o new
palavras-chave:
const err = Error("Something bad happened!");
Depois de criado, o objeto de erro apresenta três propriedades:
-
message
: uma string com a mensagem de erro. -
name
: o tipo do erro. -
stack
: um traço de pilha de execução de funções.,
Por exemplo, se criar um novo TypeError
objeto com a mensagem adequada, o message
vai levar o real erro de seqüência de caracteres, enquanto name
será "TypeError"
:
o Firefox também implementa um monte de não-padrão de propriedade como o columnNumber
filename
e lineNumber
.,
Many types of errors in JavaScript
There are many types of errors in JavaScript, namely:
Error
EvalError
InternalError
RangeError
ReferenceError
SyntaxError
TypeError
URIError
Remember, all these error types are actual constructor functions meant to return a new error object.,
no seu código, irá utilizar principalmente Error
eTypeError
, dois dos tipos mais comuns, para criar o seu próprio objecto de erro.
na Maioria das vezes, a maioria dos erros virá diretamente do motor de JavaScript, como InternalError
ou SyntaxError
.,
va x = '33';// SyntaxError: Unexpected identifier
Ou quando você usar palavras reservadas em lugares errados, como await
fora de uma async
função:
function wrong(){ await 99;}wrong();// SyntaxError: await is only valid in async function
Outro exemplo de TypeError
ocorre quando selecionamos inexistentes elementos HTML na página:
Uncaught TypeError: button is null
além dessas tradicionais objetos de erro, uma AggregateError
objeto está indo para a terra logo em JavaScript., AggregateError
é conveniente para embrulhar vários erros juntos, como veremos mais tarde.
além destes erros incorporados, no navegador também podemos encontrar:
-
DOMException
. -
DOMError
, depreciado e já não utilizado hoje.
DOMException
é uma família de erros relacionados com APIs Web., Eles são jogados quando fazemos coisas bobas no navegador, como:
document.body.appendChild(document.cloneNode(true));
O resultado:
Uncaught DOMException: Node.appendChild: May not add a Document as a child
Para uma lista completa, veja esta página no MDN.o que é uma excepção?
a maioria dos desenvolvedores acha que erro e exceções são a mesma coisa. Na realidade, um objeto de erro torna-se uma exceção apenas quando é jogado.,
Para lançar uma exceção no JavaScript podemos usar throw
, segue-se o objeto de erro:
const wrongType = TypeError("Wrong type given, expected number");throw wrongType;
A forma abreviada é mais comum, na maioria das bases de código, você irá encontrar:
throw TypeError("Wrong type given, expected number");
ou
throw new TypeError("Wrong type given, expected number");
É improvável para lançar exceções fora de uma função ou de um bloco condicional. Em vez disso, considere o seguinte exemplo:
aqui vamos verificar se o argumento da função é uma string., Se não for, abrimos uma excepção.
Tecnicamente, você poderia jogar qualquer coisa em JavaScript, não apenas objetos de erro:
throw Symbol();throw 33;throw "Error!";throw null;
no Entanto, é melhor evitar essas coisas: jogar sempre de erro adequada objetos, não primitivos. ao fazê-lo, mantém o tratamento de erros consistente através da base de código. Outros membros da equipe podem sempre esperar acessar error.message
ou error.stack
no objeto de erro.o que acontece quando abrimos uma excepção?,
exceções são como um elevador subindo: uma vez que você joga um, ele bolhas para cima na pilha de programa, a menos que seja pego em algum lugar.
considere o seguinte código:
Se você executar este código em um navegador ou no nó.js, o programa pára e relata o erro:
além disso, você pode ver a linha exata onde o erro aconteceu.
Este relatório é um traço de pilha, e é útil para rastrear problemas em seu código.
O traço da pilha vai de baixo para cima., Então, aqui:
toUppercase http://localhost:5000/index.js:3 <anonymous> http://localhost:5000/index.js:9
podemos dizer:
- algo no programa na linha 9 chamado de
toUppercase
-
toUppercase
explodiu na linha 3
além de ver este rastreamento de pilha no console do seu browser, você pode acessá-lo no stack
propriedade do objeto de erro.
Se a exceção não for capturada, ou seja, nada é feito pelo programador para pegá-la, o programa vai cair.,
Quando, e onde você pegar uma exceção no seu código depende do caso de uso específico.
Por exemplo, você pode querer propagar uma exceção na pilha para interromper o programa completamente. Isso pode acontecer para erros fatais, quando é mais seguro parar o programa em vez de trabalhar com dados inválidos.
tendo introduzido o básico vamos agora virar a nossa atenção para o tratamento de erros e exceções em código JavaScript síncrono e assíncrono.
tratamento síncrono de erros
código síncrono é a maioria das vezes simples, e assim seu tratamento de erros.,
tratamento de erros para Funções Regulares
código síncrono é executado na mesma ordem na qual é escrito. Tomemos de novo o exemplo anterior:
aqui o motor chama e executa toUppercase
. Tudo acontece em sincronia. Para capturar uma exceção de origem por tal função síncrona, podemos usar try/catch/finally
:
try { toUppercase(4);} catch (error) { console.error(error.message); // or log remotely} finally { // clean up}
Normalmente, try
lida com o feliz caminho, ou com a chamada de função que potencialmente poderia jogar.,
catch
em vez disso, captura a excepção real. Ele recebe o objeto de erro, que podemos inspecionar (e enviar remotamente para algum logger em produção).
a declaração finally
por outro lado funciona independentemente do resultado da função: se falhou ou sucedeu, qualquer código dentro de finally
irá correr.
lembre – se: try/catch/finally
é uma construção síncrona: agora tem maneira de pegar exceções provenientes de código assíncrono.,
tratamento de erros para funções geradoras
uma função geradora em JavaScript é um tipo especial de função.
ele pode ser parado e retomado à vontade, com exceção de fornecer um canal de comunicação bidirecional entre seu escopo interno e o consumidor.,
Para criar um gerador de função podemos colocar uma estrela *
depois function
palavras-chave:
function* generate() {//}
uma Vez dentro da função, podemos usar yield
para os valores de retorno:
function* generate() { yield 33; yield 99;}
O valor de retorno de uma função do gerador é um iterador objeto. Para extrair valores de um gerador podemos usar duas abordagens:
- chamando
next()
no objeto iterador., - iteração com
for...of
.
Se tomarmos o nosso exemplo, para obter valores do gerador de nós pode fazer:
function* generate() { yield 33; yield 99;}const go = generate();
Aqui go
torna-se nosso objeto iterador quando chamamos a função do gerador.
a Partir de agora podemos chamar de go.next()
para avançar a execução:
function* generate() { yield 33; yield 99;}const go = generate();const firstStep = go.next().value; // 33const secondStep = go.next().value; // 99
Geradores também funciona no sentido inverso: eles podem aceitar valores e exceções de volta a partir do chamador.,
In addition to next()
, iterator objects returned from generators have athrow()
method.
Com este método podemos interromper o programa injetando-se uma exceção para o gerador de:
Para capturar tal erro seria envolver o seu código dentro do gerador com try/catch
(e finally
se necessário):
function* generate() { try { yield 33; yield 99; } catch (error) { console.error(error.message); }}
Gerador de funções também podem lançar exceções para o exterior., O mecanismo de captura dessas exceções é o mesmo para a captura de exceções síncronas: try/catch/finally
.
Aqui está um exemplo de uma função geradora consumida do exterior com for...of
:
Aqui iteramos o caminho feliz dentro de um try
bloco. Se ocorrerem exceções, paramos com catch
.
o tratamento assíncrono de erros
JavaScript é síncrono por natureza, sendo uma linguagem de simples rosca.,
Host environments like browsers engines augment JavaScript with a number of Web API for interacting with external systems, and for dealing with I/O bound operations.exemplos de assíncronicidade no navegador são timeouts, eventos, promessa.o tratamento de erros no mundo assíncrono é distinto do seu homólogo síncrono.
vamos ver alguns exemplos.
de tratamento de Erro para temporizadores
No início de suas explorações com JavaScript, depois de aprender sobre o try/catch/finally
, você pode ser tentado a colocá-lo em torno de qualquer bloco de código.,
considere o seguinte trecho:
function failAfterOneSecond() { setTimeout(() => { throw Error("Something went wrong!"); }, 1000);}
Esta função lança cerca de 1 segundo. Qual é a maneira certa de lidar com esta excepção?
O seguinte exemplo não funciona:
Como dissemos, try/catch
é síncrono. Por outro lado, temos setTimeout
, uma API de navegador para temporizadores.
no momento em que o callback passou para setTimeout
corre, o nosso try/catch
desapareceu há muito. O programa vai falhar porque não conseguimos capturar a excepção.,
Eles viajam em duas faixas distintas:
Track A: --> try/catchTrack B: --> setTimeout --> callback --> throw
Se a gente não quer travar o programa, para lidar com o erro corretamente devemos mover try/catch
dentro de retorno de chamada para setTimeout
.
mas, esta abordagem não faz muito sentido na maioria das vezes. Como veremos mais tarde, o tratamento assíncrono de erros com promessas proporciona uma melhor ergonomia.,
tratamento de erros para eventos
nós HTML no modelo de objeto do documento estão conectados aEventTarget
, o ancestral comum para qualquer emissor de eventos no navegador.
isso significa que podemos ouvir eventos em qualquer elemento HTML da página.
(nó.js irá suportar EventTarget
em um lançamento futuro).
a mecânica de tratamento de erros para eventos DOM segue o mesmo esquema de qualquer API Web assíncrona.
considere o seguinte exemplo:
Aqui nós lançamos uma exceção assim que o botão é clicado. Como é que o apanhamos?, Este padrão não funciona, e não impede que o programa de antecipação de:
Como no exemplo anterior com setTimeout
, qualquer chamada de retorno passada para addEventListener
é executada de forma assíncrona:
Track A: --> try/catchTrack B: --> addEventListener --> callback --> throw
Se a gente não quer travar o programa, para lidar com o erro corretamente devemos mover try/catch
dentro de retorno de chamada para addEventListener
.
mas, novamente, há pouco de valor em fazer isso.,
tal como com setTimeout
, a excepção lançada por um caminho de código assíncrono não é captável do exterior, e irá interromper o seu programa.
nas secções seguintes veremos como as promessas e async/await
podem facilitar o tratamento de erros para o código assíncrono.
que tal um erro?
elementos HTML têm uma série de manipuladores de eventos comoonclick
,onmouseenter
,onchange
para nomear alguns.
Há também onerror
, mas não tem nada a ver com throw
e amigos.,
O onerror
manipulador de eventos dispara sempre um elemento HTML como um <img>
tag ou um <script>
atinge um recurso inexistente.,b4″>// omitted<body><img src="https://www.valentinog.com/blog/error/nowhere-to-be-found.png" alt="So empty!"></body>// omitted
Ao visitar um documento HTML com a falta de um ou inexistente recurso o console do seu browser registros de erro:
GET http://localhost:5000/https://www.valentinog.com/blog/error/nowhere-to-be-found.png
Nas nossas JavaScript temos a chance de “pegar” este erro com o manipulador de evento apropriado:
const image = document.querySelector("img");image.onerror = function(event) { console.log(event);};
Ou melhor:
const image = document.querySelector("img");image.addEventListener("error", function(event) { console.log(event);});
Este modelo é útil para o carregamento alternativo de recursos no local da falta de imagens ou scripts.,
Mas lembre-se: onerror
, não tem nada a ver com throw
ou try/catch
.
tratamento de erros com promessa
para ilustrar o tratamento de erros com promessa vamos “promisificar” um dos nossos exemplos originais. Nós ajustar a função a seguir:
em Vez de retornar uma cadeia de caracteres simples, ou uma exceção, utilizamos, respectivamente, Promise.reject
e Promise.resolve
para tratar de erro e de sucesso:
(Tecnicamente não há nada assíncrona neste código, mas serve bem para ilustrar o ponto).,
Agora que a função é “promisified” podemos anexar then
para consumir o resultado, e catch
para o tratamento do rejeitada Promessa:
toUppercase(99) .then(result => result) .catch(error => console.error(error.message));
Este código será de log:
Wrong type given, expected a string
No reino da Promessa, catch
é a construção de manipulação de erros.,
além de catch
e then
temos também finally
, semelhante ao finally
no try/catch
.
Como o seu síncrona “relativo”, da Promessa finally
é executado independentemente da Promessa resultado:
toUppercase(99) .then(result => result) .catch(error => console.error(error.message)) .finally(() => console.log("Run baby, run"));
tenha Sempre em mente que qualquer chamada de retorno passada para then/catch/finally
é tratada de forma assíncrona pelo Microtask Fila. São micro-tarefas com precedência sobre macro-Tarefas, como eventos e cronómetros.,
Promessa, de erro, e jogar
Como prática recomendada quando rejeitar uma Promessa é conveniente fornecer um objeto de erro:
Promise.reject(TypeError("Wrong type given, expected a string"));
Ao fazê-lo, manter o tratamento de erro consistente através da base de código. Outros membros da equipe podem sempre esperar acessar error.message
, e mais importante você pode inspecionar traços de pilha.
In addition toPromise.reject
, we can exit from a Promise chain by throwing an exception.,
Considere o exemplo a seguir:
Promise.resolve("A string").then(value => { if (typeof value === "string") { throw TypeError("Expected a number!"); }});
Nós resolver uma Promessa com uma seqüência de caracteres e, em seguida, a cadeia é imediatamente quebrado com throw
.
Para parar a propagação de exceção usamos catch
, como de costume:
Este padrão é comum em fetch
, onde podemos verificar o objeto de resposta em busca de erros:
Aqui, a exceção pode ser interceptada com catch
., Se falharmos, ou decidirmos não apanhá-lo lá, a excepção é livre para subir na pilha.
isto não é mau por si só, mas diferentes ambientes reagem de forma diferente a rejeições inesperadas.
nó.js por exemplo, no futuro, deixar de falha de qualquer programa onde Promessa rejeições são não-manipulado:
DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Melhor que você pegá-los!
tratamento de erros para temporizadores “Promocionais”
com temporizadores ou eventos não é possível pegar exceções lançadas de um callback., Vimos um exemplo na seção anterior:
uma solução oferecida pela promessa consiste na” promisificação ” do nosso código. Basicamente, os envolvemos com o nosso timer com uma Promessa:
function failAfterOneSecond() { return new Promise((_, reject) => { setTimeout(() => { reject(Error("Something went wrong!")); }, 1000); });}
Com reject
temos uma Promessa de rejeição, o que acarreta um erro de objeto.,
neste ponto, podemos tratar a exceção com catch
:
failAfterOneSecond().catch(reason => console.error(reason.message));
Nota: é comum o uso de value
como o de retornar o valor de uma Promessa, e reason
como retornar o objeto a partir de uma rejeição.
nó.o js tem um utilitário chamado promisify para facilitar a” promisificação ” das APIs de retorno de estilo antigo.tratamento de erros na promessa.,todos
O método estático Promise.all
aceita uma matriz de Promessa, e retorna um array de todos os resultados de resolução de Promessa:
Se qualquer um desses Promessa rejeita, Promise.all
rejeita com o erro do primeiro rejeitada Promessa.
Para lidar com essas situações no Promise.all
nós usamos catch
, como fizemos na seção anterior:
Para executar uma função, independentemente do resultado da Promise.all
, novamente, podemos usar finally
:
de tratamento de Erro na Promessa.,qualquer
podemos considerar Promise.any
(Firefox > 79, Chrome > 85) como o oposto de Promise.all
.
Enquanto Promise.all
devolve uma falha, mesmo se uma única Promessa na matriz rejeita, Promise.any
nos dá sempre o primeiro resolvido Promessa (se presente na matriz), independentemente de qualquer rejeição ocorreu.
In case instead all the Promise passed to Promise.any
reject, the resulting error is an AggregateError
., Considere o seguinte exemplo:
aqui lidamos com o erro com catch
., O resultado deste código é:
AggregateError: No Promise in Promise.any was resolvedAlways runs!
AggregateError
objeto tem as mesmas propriedades de uma Error
, além de uma errors
propriedade:
// .catch(error => console.error(error.errors))//
Esta propriedade é uma matriz de cada indivíduo erro produzido pela rejeitar:
de tratamento de Erro na Promessa.,race
the static method Promise.race
accepts an array of Promise:
The result is the first Promise who wins the “race”.que tal rejeições? Se a rejeitar a Promessa não é o primeiro a aparecer na matriz de entrada, Promise.race
resolve:
Se a rejeição em vez disso, aparece como o primeiro elemento da matriz, Promise.race
rejeita, e nós devemos pegar a rejeição:
de tratamento de Erro na Promessa.allSettled
Promise.allSettled
é uma adição ECMAScript 2020 à linguagem.,
não há muito para lidar com este método estático, uma vez que o resultado será sempre uma promessa resolvida, mesmo que uma ou mais promessas de entrada rejeitem.
considere o seguinte exemplo:
passamos para Promise.allSettled
uma matriz consistindo de duas promessas: uma resolvida e outra rejeitada.
neste caso catch
nunca será atingido. finally
em vez disso corre.,
O resultado deste código, registrado no then
é:
o tratamento de Erro para async/await
async/await
em JavaScript denota funções assíncronas, mas a partir de um leitor de vista eles se beneficiam de toda a legibilidade do síncrona funções.,
Para manter as coisas simples, nós vamos levar a nossa anterior função síncrona toUppercase
, e nós transformá-la em uma função assíncrona colocando async
antes de function
palavras-chave:
Apenas pelo prefixo de uma função com async
fazemos com que a função retorne uma Promessa., Isso significa que podemos cadeia then
catch
e finally
após a chamada de função:
Quando a gente joga a partir de uma async
função de exceção torna-se causa de rejeição para a Promessa fundamental.
qualquer erro pode ser interceptado com catch
do lado de fora.
Mais importante, além deste estilo podemos usar try/catch/finally
, tanto quanto faríamos com uma função síncrona.,
No exemplo seguinte nós chamamos de toUppercase
a partir de outra função, consumer
, que, convenientemente, molda-se a chamada de função com try/catch/finally
:
O resultado é:
Wrong type given, expected a stringAlways runs!
Sobre o mesmo assunto: Como Jogar Erros De Assíncrona de Funções em JavaScript?os geradores de async em JavaScript são funções geradoras capazes de fornecer promessas em vez de valores simples.,
combinam funções geradoras comasync
. O resultado é uma função geradora cujos objetos iteradores expõem uma promessa ao consumidor.
Para criar um gerador assíncrono declaramos um gerador de função com a estrela *
, com o prefixo async
:
async function* asyncGenerator() { yield 33; yield 99; throw Error("Something went wrong!"); // Promise.reject}
Sendo baseado na Promessa, as mesmas regras para o tratamento de erros se aplicam aqui., throw
in an async generator causes a Promise rejection, which we intercept withcatch
.
para retirar promessas de um gerador async podemos usar duas abordagens:
-
then
manipuladores.iteração.
do exemplo acima sabemos com certeza que haverá uma exceção após os dois primeiros id
., Isso significa que nós podemos fazer:
A saída desse código é:
{ value: 33, done: false }{ value: 99, done: false }Something went wrong!
A outra abordagem utiliza assíncrono iteração com for await...of
. Para usar a iteração async, precisamos envolver o consumidor com uma função async
.,
Aqui está o exemplo completo:
E async/await
podemos lidar com qualquer potencial de exceção com try/catch
:
A saída desse código é:
3399Something went wrong!
O iterador objeto retornado de uma assíncrono gerador de função tem também uma throw()
método, muito parecido com o seu equivalente síncrono.,
Chamar throw()
sobre o iterador objeto aqui não lançar uma exceção, mas uma Promessa de rejeição:
Para lidar com essa situação de fora que nós podemos fazer:
go.throw(Error("Let's reject!")).catch(reason => console.error(reason.message));
Mas não vamos esquecer que o iterador de objetos throw()
enviar exceção dentro do gerador. Isto significa que também podemos aplicar o seguinte padrão:
tratamento de erros no nó.js
tratamento síncrono de erros no nó.js
tratamento síncrono de erros no nó.,o js não difere muito do que vimos até agora.
para código síncrono, try/catch/finally
funciona bem.no entanto, as coisas ficam interessantes se olharmos para o mundo assíncrono.
tratamento assíncrono de erros no nó.js: the callback pattern
For asynchronous code, Node.js baseia-se fortemente em duas expressões:
- o padrão de callback.emissores de eventos.
no padrão de callback, nó assíncrono.as APIs js aceitam uma função que é tratada através do ciclo de eventos e executada assim que a pilha de chamadas estiver vazia.,
Considere o código a seguir:
Se extrair a chamada de retorno a partir desta listagem, podemos ver como deve lidar com os erros:
//function(error, data) { if (error) console.error(error); // do stuff with the data }//
Se os erros que surge da leitura do dado caminho com fs.readFile
, obtemos um objeto de erro.
neste ponto podemos:
- simplesmente registar o objecto de erro como fizemos.abre uma excepção.
- passa o erro para outra chamada de resposta.,
para lançar uma excepção podemos fazer:
no entanto, tal como acontece com eventos e cronómetros no DOM, esta excepção irá interromper o programa. Os seguintes tentar detê-lo com try/catch
não funcionam:
de Passar o erro para outro de retorno de chamada é a opção preferida, se não queremos a falha do programa:
Aqui errorHandler
é o que o nome sugere, uma simples função para manipulação de erro:
Assíncrona erro de processamento no Nó.js: emissores de eventos
muito do que você faz no nó.js é baseado em eventos., Na maioria das vezes você interage com um objeto emissor e alguns observadores escutando mensagens.
qualquer módulo movido por eventos (como o net, por exemplo) no nó.js extends a root class named EventEmitter
.
EventEmitter
in Node.js has two fundamental methods: on
and emit
.
considere este Servidor HTTP simples:
Aqui nós escutamos para dois eventos: escuta e conexão.
além destes eventos, os emissores de eventos expõem também um evento de erro, disparado em caso de erros.,
Se você executar esse código escutando na porta 80 em vez do exemplo anterior, você irá receber uma exceção:
Saída:
Para pegá-lo, podemos registrar um manipulador de eventos para o erro:
server.on("error", function(error) { console.error(error.message);});
Isto irá imprimir:
listen EACCES: permission denied 127.0.0.1:80
além disso, o programa não falha.
para saber mais sobre o tópico, considere também ler “tratamento de erros no nó.js”.,
encerrando
neste guia cobrimos o tratamento de erros em JavaScript para todo o espectro, desde o código síncrono simples até primitivos assíncronos avançados.
Existem muitas maneiras em que uma exceção pode se manifestar em nossos programas JavaScript.as excepções ao código síncrono são as mais simples de capturar. Exceções de caminhos de código assíncronos podem ser difíceis de lidar.
entretanto, novas APIs JavaScript no navegador são quase todas direcionadas para Promise
., Este padrão invasivo torna mais fácil para lidar com exceções com then/catch/finally
ou com try/catch
para async/await
.
Depois de ler este guia você deve ser capaz de reconhecer todas as diferentes situações que podem surgir em seus programas, e pegar suas exceções corretamente.Obrigado por ler e permanecer sintonizado!
Este post também está disponível em:
- Japonês
- Chinês
Deixe uma resposta