Quando comecei a trabalhar com o Express e tentei descobrir como lidar com erros, tive dificuldades. Havia um sentimento de que ninguém escreveu sobre o que eu precisava. Como resultado, tive que procurar respostas para minhas perguntas. Hoje, quero contar tudo o que sei sobre o tratamento de erros nos aplicativos Express. Vamos começar com erros síncronos.

Tratamento de erros síncronos
Se você precisar manipular um erro síncrono, poderá, em primeiro lugar, usando a instrução
throw
,
throw
esse erro no manipulador de solicitações Express. Observe que os manipuladores de solicitações também são chamados de "controladores", mas eu prefiro usar o termo "manipulador de solicitações", como me parece mais claramente.
Aqui está o que parece:
app.post('/testing', (req, res) => { throw new Error('Something broke! ') })
Esses erros podem ser detectados usando o manipulador de erros Express. Se você não escreveu seu próprio manipulador de erros (falaremos mais sobre isso abaixo), o Express tratará o erro usando o manipulador padrão.
Aqui está o que o manipulador de erros Express padrão faz:
- Define o código de status da resposta HTTP como 500.
- Envia uma resposta de texto para a entidade que está executando a solicitação.
- Registra uma resposta de texto no console.
Mensagem de erro exibida no consoleManipulação de erro assíncrona
Para manipular erros assíncronos, você precisa enviar um erro ao manipulador de erros Express através do
next
argumento:
app.post('/testing', async (req, res, next) => { return next(new Error('Something broke again! ')) })
É isso que chega ao console ao registrar esse erro.
Mensagem de erro exibida no consoleSe você usar a construção assíncrona / aguardada em um aplicativo Express, precisará usar uma função de wrapper como
express-async-handler . Isso permite escrever código assíncrono sem blocos
try / catch . Leia mais sobre assíncrono / espera no Express
aqui .
const asyncHandler = require('express-async-handler') app.post('/testing', asyncHandler(async (req, res, next) => {
Depois que o manipulador de solicitações é agrupado no
express-async-handler
, é possível, como descrito acima, gerar um erro usando a instrução
throw
. Este erro irá para o manipulador de erros Express.
app.post('/testing', asyncHandler(async (req, res, next) => { throw new Error('Something broke yet again! ') }))
Mensagem de erro exibida no consoleEscrevendo seu próprio manipulador de erros
Os manipuladores de erro expressos usam 4 argumentos:
- erro
- req
- res
- próximo
Você precisa colocá-los após manipuladores e rotas intermediárias.
app.use() app.get() app.post() app.put() app.delete()
Se você criar seu próprio manipulador de erros, o Express deixará de usar o manipulador de erros padrão. Para lidar com o erro, você precisa gerar uma resposta para o aplicativo front-end que abordou o terminal no qual o erro ocorreu. Isso significa que você precisa fazer o seguinte:
- Gere e envie um código de status de resposta adequado.
- Forme e envie uma resposta adequada.
Qual código de status é apropriado em cada caso específico depende do que exatamente aconteceu. Aqui está uma lista de erros comuns que você deve estar preparado para manipular:
- Erro
400 Bad Request
. Usado em duas situações. Primeiro, quando o usuário não incluiu o campo obrigatório na solicitação (por exemplo, o campo com informações do cartão de crédito não foi preenchido no formulário de pagamento enviado). Em segundo lugar, quando a solicitação contém dados incorretos (por exemplo, digitando senhas diferentes no campo de senha e no campo de confirmação de senha). - Erro
401 Unauthorized
. Este código de status de resposta será aplicado se o usuário tiver inserido credenciais incorretas (como nome de usuário, endereço de email ou senha). - Erro
403 Forbidden
. Usado quando o usuário não tem acesso permitido ao terminal. - Erro
404 Not Found
. É usado nos casos em que o terminal não pode ser detectado. - Erro
500 Internal Server Error
Erro 500 Internal Server Error
. É aplicada quando a solicitação enviada pelo front-end é formada corretamente, mas ocorreu algum erro no back-end.
Depois que o código de status de resposta apropriado é definido, ele deve ser configurado usando
res.status
:
app.use((error, req, res, next) => {
O código de status da resposta deve corresponder à mensagem de erro. Para fazer isso, envie o código de status junto com o erro.
A maneira mais fácil de fazer isso é com o pacote de
erros http . Ele permite enviar três informações erradas:
- O código de status da resposta.
- A mensagem associada ao erro.
- Qualquer dado que precise ser enviado (isso é opcional).
Veja como instalar o pacote de
http-errors
:
npm install http-errors --save
Veja como usar este pacote:
const createError = require('http-errors')
Considere um exemplo que permitirá que você entenda tudo isso corretamente.
Imagine que estamos tentando encontrar um usuário no endereço de e-mail dele. Mas este usuário não pode ser encontrado. Como resultado, decidimos enviar um erro de
User not found
em resposta à solicitação correspondente, informando ao chamador que o usuário não foi encontrado.
Aqui está o que precisamos fazer ao criar o erro:
- Defina o código de status da resposta como
400 Bad Request
incorreta (afinal, o usuário inseriu dados incorretos). Este será o nosso primeiro parâmetro. - Envie uma mensagem para o chamador como
User not found
. Este será o segundo parâmetro.
app.put('/testing', asyncHandler(async (req, res) => { const { email } = req.body const user = await User.findOne({ email })
Você pode obter o código de status usando a construção
error.status
e a mensagem de erro usando
error.message
:
O resultado de erros de log no consoleEm seguida, o estado de resposta é definido usando
res.status
e a mensagem é gravada em
res.json
:
app.use((error, req, res, next) => {
Pessoalmente, prefiro enviar um código de status, mensagem e resultado de rastreamento de pilha em tais respostas. Isso facilita a depuração.
app.use((error, req, res, next) => {
▍ Código de status da resposta padrão
Se a origem do erro não for
createError
, ela não terá a propriedade
status
. Aqui está um exemplo no qual foi feita uma tentativa de ler um arquivo inexistente usando
fs.readFile
:
const fs = require('fs') const util = require('util')
Esse objeto de erro não terá a propriedade
status
:
app.use((error, req, res, next) => { console.log('Error status: ', error.status) console.log('Message: ', error.message) })
O resultado de erros de log no consoleNesses casos, você pode definir o código de erro padrão. Ou seja, estamos falando sobre o
500 Internal Server Error
:
app.use((error, req, res, next) => { res.status(error.status || 500) res.json({ status: error.status, message: error.message, stack: error.stack }) })
HanAlterando o código de status do erro
Suponha que vamos ler um determinado arquivo usando os dados fornecidos pelo usuário. Se esse arquivo não existir, significa que precisamos fornecer um erro
400 Bad Request
. Afinal, o servidor não pode ser encontrado porque o arquivo não pode ser encontrado.
Nesse caso, você precisa usar a construção try / catch para capturar o erro original. Então você precisa recriar o objeto de erro usando
createError
:
app.get('/testing', asyncHandler(async (req, res, next) => { try { const { file } = req.body const contents = await readFilePromise(path.join(__dirname, file)) } catch (error) { throw createError(400, `File ${file} does not exist`) } })
▍ 404 tratamento de erros
Se a solicitação passou por todos os manipuladores e rotas intermediárias, mas não foi processada, isso significa que o terminal correspondente a essa solicitação não foi encontrado.
Para lidar com erros
404 Not Found
, é necessário adicionar, entre as rotas e o manipulador de erros, um manipulador adicional. Veja como é a criação do objeto de erro 404:
Detalhes do erroNotes ERR_HTTP_HEADERS_SENT notas de erro
Não entre em pânico se aparecer a mensagem de erro
ERR_HTTP_HEADERS_SENT: Cannot set headers after they are sent to the client
. Isso ocorre porque no mesmo manipulador o método que define os cabeçalhos de resposta é chamado repetidamente. Aqui estão os métodos que chamam para definir automaticamente os cabeçalhos de resposta:
- res.send
- res.json
- res.render
- res.sendFile
- res.sendStatus
- res.end
- res.redirect
Portanto, por exemplo, se você chamar os
res.json
e
res.json
no mesmo manipulador de respostas, receberá o erro
ERR_HTTP_HEADERS_SENT
:
app.get('/testing', (req, res) => { res.render('new-page') res.json({ message: '¯\_(ツ)_/¯' }) })
Como resultado, se você encontrar esse erro, verifique cuidadosamente o código do manipulador de respostas e verifique se não há situações nas quais vários dos métodos descritos acima sejam chamados.
▍ Tratamento de erros e streaming de dados
Se algo der errado ao transmitir a resposta ao front-end, você poderá encontrar o mesmo erro
ERR_HTTP_HEADERS_SENT
.
Nesse caso, o tratamento de erros deve ser passado para os manipuladores padrão. Esse manipulador envia um erro e fecha automaticamente a conexão.
app.use((error, req, res, next) => {
Sumário
Hoje eu contei tudo o que sei sobre tratamento de erros no Express. Espero que isso ajude você a escrever aplicativos Express mais confiáveis.
Caros leitores! Como você lida com erros em seus projetos Node.js.
