Guia para tratamento de exceções no Express PlatoBlockchain Data Intelligence. Pesquisa vertical. Ai.

Guia para Tratamento de Exceções no Express

Introdução

Exceções e erros podem ocorrer enquanto os usuários interagem com qualquer aplicativo, cabe aos engenheiros de software escolher um meio para lidar com qualquer erro que possa surgir – consciente ou inconscientemente. Como resultado, os desenvolvedores de back-end que constroem APIs com o Express trabalham para garantir que estejam criando uma API útil, eficiente e utilizável. O mais importante é lidar com os erros de forma a construir um sistema robusto, pois isso ajuda a reduzir o tempo de desenvolvimento, erros absolutos, problemas de produtividade e determina o sucesso ou a escalabilidade do desenvolvimento de software.

Você precisa registrar a mensagem de erro, suprimir o erro, notificar os usuários sobre o erro ou escrever código para lidar com erros? Maravilha não mais.

Neste guia, aprenderemos como criar uma base de código robusta de tratamento de erros para aplicativos Express, que servirá para ajudar a detectar erros de aplicativos e tomar ações ideais para recuperar qualquer aplicativo de falha normal durante o tempo de execução.

Observação: Usaremos o Postman para testar a API em nossa demonstração. Você pode baixá-lo no Página de download do carteiro. Como alternativa, você pode simplesmente usar o navegador, a linha de comando curl ou qualquer outra ferramenta com a qual você esteja familiarizado.

O que é Tratamento de Erros?

No desenvolvimento de software, existem dois tipos diferentes de exceções: operacional e Programático.

  • Falhas operacionais podem surgir durante o tempo de execução e, para evitar que o aplicativo seja encerrado abruptamente, devemos lidar com essas exceções com eficiência por meio de métodos eficientes de tratamento de erros.
  • Exceções programáticas são lançadas manualmente por um programador, quando surge um estado excepcional.

Você pode pensar em exceções operacionais como exceções “inesperadas, mas previstas” (como acessar um índice fora dos limites) e exceções programáticas como exceções “esperadas e previstas” (como uma exceção de formatação de número).

O tratamento de exceção é o procedimento usado para encontrar e corrigir falhas em um programa. O tratamento de erros envia mensagens que incluem o tipo de erro ocorrido e a pilha em que o erro ocorreu.

Observação: Na ciência da computação, as exceções são recuperáveis ​​e geralmente decorrem de problemas operacionais ou programáticos durante o tempo de execução. Erros geralmente surgem de fatores externos, como limitações de hardware, problemas com conectividade, falta de memória, etc. Em JavaScript, os termos são muitas vezes usados ​​de forma intercambiável e exceções personalizadas são derivadas do Error aula. O Error A própria classe representa erros e exceções.

No Express, o tratamento de exceções refere-se a como o Express se configura para capturar e processar exceções síncronas e assíncronas. A vantagem do tratamento de exceções no Express é que, como desenvolvedor, você não precisa escrever seus próprios manipuladores de exceção; O Express vem com um manipulador de exceção padrão. O manipulador de exceção ajuda a identificar erros e relatá-los ao usuário. Ele também fornece várias estratégias corretivas e as implementa para mitigar exceções.

Embora isso possa parecer um monte de coisas ocultas, o tratamento de exceções no Express não retarda o processo geral de um programa ou interrompe sua execução.

Compreendendo o tratamento de exceções no Express

Com o manipulador de erros padrão que vem com o Express, temos em mãos um conjunto de funções de middleware que ajudam a detectar erros em manipuladores de rota automaticamente. Em breve, criaremos um projeto para colocar em prática a teoria de como retornar os devidos erros em um app Express e como não vazar informações sigilosas.

Definindo a função de middleware no Express

As funções de middleware de tratamento de erros são definidas de tal forma que aceitam um Error object como o primeiro parâmetro de entrada, seguido pelos parâmetros padrão de qualquer outra função de middleware: request, response e next. O next() A função pula todo o middleware atual para o próximo manipulador de erros do roteador.

Configurando o tratamento de erros no Express

Execute o seguinte comando em seu terminal para criar um aplicativo Node and Express:

$ mkdir error-handling-express

Na pasta recém criada, vamos inicializar um novo projeto Node:

$ cd error-handling-express && npm init -y

Isso cria um package.json arquivo em nossa pasta.

Para criar um servidor Express em nosso aplicativo Node, precisamos instalar o express pacote dotenv para carregar automaticamente variáveis ​​de ambiente em .env arquivo em process.env objeto, e nodemon para reiniciar o aplicativo do nó se uma alteração de arquivo for observada no diretório.

$ npm install express dotenv nodemon

A seguir, crie um app.js arquivo na pasta do projeto que servirá como arquivo de índice para o aplicativo.

Agora que instalamos todas as dependências necessárias para nosso aplicativo Express, precisamos configurar o script para ler o aplicativo no package.json Arquivo. Para conseguir isso, o package.json arquivo, para que o scripts objeto é como mostrado abaixo:

"scripts": {
    "start": "nodemon app.js"
},

Alternativamente, você pode pular usando nodemon, E use node app.js ao invés.

Configurando um servidor Express

Para configurar o servidor, primeiro temos que importar os vários pacotes para app.js. Também criaremos um .env arquivo no diretório do projeto – para armazenar todas as variáveis ​​de ambiente para o aplicativo:



const express = require('express')
require('dotenv').config

PORT=4000 

Definimos o número da porta para o aplicativo em .env, que é carregado e lido por dotenv, e pode ser acessado posteriormente.

Inicializando o Express Server

Agora, precisamos inicializar o servidor Express e fazer nosso aplicativo escutar o número da porta do aplicativo, junto com uma solicitação para uma rota de teste – /test. vamos atualizar app.js, abaixo das instruções de importação:


const app = express();
const port = process.env.PORT || 4000;

app.get("/test", async (req, res) => {
    return res.status(200).json({ success: true });
});

app.listen(port, () => {
    console.log(`Server is running at port ${port}`);
});

A partir daqui, aprenderemos como lidar com vários casos de uso de erros operacionais que podem ser encontrados no Express.

Tratamento de erros não encontrados no Express

Suponha que você precise buscar todos os usuários de um banco de dados de usuários; try/catch bloco - na esperança de pegar qualquer erro que poderia projetar no catch quadra:


const getUser = () => undefined;

app.get("/get-user", async (req, res) => {
	try {
		const user = getUser();
		if (!user) {
			throw new Error('User not found');
		}
	} catch (error) {
	    
		console.log(error); 
		
		res.status(400).send(error.message) 
	}
	return res.status(200).json({
		success: true
	});
});

Isto resulta em:

User not found

Agora, quando essa requisição é feita (você pode testar usando o Postman) e não existe nenhum usuário no banco de dados, o cliente recebe uma mensagem de erro que diz “Usuário não encontrado”. Além disso, você notará que o erro também está registrado no console.

Otimizando o Tratamento de Erros com o Middleware do Manipulador de Erros

Podemos otimizar o desenvolvimento criando um middleware de tratamento de erros que viria no final de todas as rotas definidas, de modo que, se um erro for lançado em uma das rotas, o Express irá automaticamente dar uma olhada no próximo middleware e continuar descendo a lista até chegar ao manipulador de erros. O manipulador de erros processará o erro e também enviará uma resposta ao cliente.

Confira nosso guia prático e prático para aprender Git, com práticas recomendadas, padrões aceitos pelo setor e folha de dicas incluída. Pare de pesquisar comandos Git no Google e realmente aprender -lo!

Para começar, crie uma pasta chamada middleware no diretório do projeto, e nesta pasta, crie um arquivo chamado errorHandler.js que define o manipulador de erros:

const errorHandler = (error, req, res, next) => {
    
    console.log(error); 
    
    res.status(400).send(error.message); 
}
module.exports = errorHandler;

Em nossa função de middleware, conscientizamos o Express de que esta não é uma função de middleware básica, mas um manipulador de erros, adicionando o error parâmetro antes dos 3 parâmetros básicos.

Agora, usaremos o manipulador de erros em nossa demonstração app.js e lide com o erro inicial de buscar usuários com o middleware do manipulador de erros, como mostrado abaixo:


const getUser = () => undefined;

app.get("/get-user", async (req, res, next) => {
	try {
		const user = getUser();
		if (!user) {
			throw new Error("User not found");
		}
	} catch (error) {
		return next(error);
	}
});

app.use(errorHandler);

Podemos otimizar ainda mais nosso código, criando uma abstração em torno do try/catch lógica. Podemos conseguir isso criando uma nova pasta no diretório do projeto chamada utils, e nele, crie um arquivo chamado tryCatch.js.

Para abstrair o try-catch lógica – podemos definir uma função que aceita outra função (conhecida como controlador) como seu parâmetro e retorna um async função que manterá um try/catch para qualquer controlador recebido.

Se ocorrer um erro no controlador, ele é detectado no catch bloco e a próxima função é chamada:


const tryCatch = (controller) => async (req, res, next) => {
	try {
		await controller(req, res);
	} catch (error) {
		return next(error);
	}
};
module.exports = tryCatch;

Com o try/catch abstração, podemos refatorar nosso código para torná-lo mais sucinto pulando o try-catch cláusula explicitamente ao buscar usuários no app.js:


const getUser = () => undefined;

app.get(
	"/get-user",
	tryCatch(async (req, res) => {
		const user = getUser();
		if (!user) {
			throw new Error("User not found");
		}
		res.status(400).send(error.message);
	})
);

Nós abstraímos com sucesso a lógica try-catch e nosso código ainda funciona como antes.

Lidando com erros de validação no Express

Para esta demonstração, criaremos uma nova rota em nosso aplicativo Express para login - para validar um ID de usuário no login. Primeiro, instalaremos o joi pacote, para ajudar na criação de um esquema, com o qual podemos impor requisitos:

$ npm i joi

Em seguida, crie um esquema que é um Joi.object com uma userId que deve ser um número e é obrigatório – o que significa que a solicitação deve corresponder a um objeto com um ID de usuário.

Nós podemos usar o validate() no objeto do esquema para validar cada entrada no esquema:


const schema = Joi.object({
	userId: Joi.number().required(),
});

app.post(
	"/login",
	tryCatch(async (req, res) => {
		const {error, value} = schema.validate({});
		if (error) throw error;
	})
);

Se um objeto vazio for passado para o validate() método, o erro seria tratado normalmente e a mensagem de erro seria enviada ao cliente:

No console, também temos acesso a um details array que inclui vários detalhes sobre o erro que podem ser comunicados ao usuário, se necessário.

Para lidar especificamente com erros de validação de forma a passar os detalhes de erro apropriados por erro de validação, o middleware do manipulador de erros pode ser refatorado:


const errorHandler = (error, req, res, next) => {
	console.log(error); 

	if (error.name === "ValidationError") {
		return res.status(400).send({
			type: "ValidationError",
			details: error.details,
		});
	}

	res.status(400).send(error.message); 
};

module.exports = errorHandler;

Com o errorHandler.js agora customizado, quando fazemos a mesma requisição com um objeto vazio passado para o validate() método:

Guia para tratamento de exceções no Express PlatoBlockchain Data Intelligence. Pesquisa vertical. Ai.

Agora temos acesso a um objeto customizado que retorna mensagens de forma mais legível/amigável. Dessa forma, somos capazes de enviar e lidar com diferentes tipos de erros com base no tipo de erro recebido.

Conclusão

Neste guia, examinamos todos os aspectos do tratamento de erros do Express.js, incluindo como o código síncrono e assíncrono é tratado por padrão, como criar suas próprias classes de erro, como escrever funções de middleware personalizadas de tratamento de erros e fornecer next como o manipulador de captura final

Como acontece com todas as tarefas, também existem práticas recomendadas durante o desenvolvimento, que incluem tratamento eficaz de erros, e hoje aprendemos como podemos lidar com erros em um aplicativo Express de maneira robusta.

Lidar com erros adequadamente não significa apenas reduzir o tempo de desenvolvimento ao encontrar bugs e erros facilmente, mas também desenvolver uma base de código robusta para aplicativos de grande escala. Neste guia, vimos como configurar o middleware para lidar com erros operacionais. Algumas outras maneiras de melhorar o tratamento de erros incluem: não enviar rastreamentos de pilha, interromper processos normalmente para lidar com exceções não capturadas, fornecer mensagens de erro apropriadas, enviar logs de erro e configurar uma classe que estenda o Error classe.

Espero que os exemplos que usei neste tutorial tenham sido agradáveis ​​para você. Cobri vários cenários que você poderia encontrar ao escrever um aplicativo Express para uso no mundo real sobre gerenciamento de erros. Por favor, deixe-me saber se há alguma coisa que eu perdi. Isso nos beneficiará e também me ajudará a aprender mais. Tenha um bom dia e obrigado por ler.

Você pode consultar todo o código-fonte usado no artigo sobre Github.

Recursos adicionais

Carimbo de hora:

Mais de Abuso de pilha