O que são Promises no Node.js?
Promises são objetos usados para representar a eventual conclusão ou falha de uma operação assíncrona. Quando você utiliza uma Promise no Node.js, ela pode estar em um dos três estados: pendente, cumprida ou rejeitada.
- Pendente: A Promise ainda não foi resolvida ou rejeitada.
- Cumprida: A Promise foi resolvida com sucesso, e o valor de retorno está disponível.
- Rejeitada: A Promise falhou e foi rejeitada, geralmente devido a um erro.
Quando uma Promise é rejeitada, é fundamental tratá-la adequadamente, caso contrário, isso pode causar erros não tratados e falhas na execução do código. A boa prática é usar .catch(), async/await ou manipulação de erros adequada para garantir que todos os erros sejam capturados e tratados.
1. Usando .catch()
para tratar erros em Promises
Uma das maneiras mais comuns de tratar erros em Promises no Node.js é utilizando o método .catch(). O .catch() é um manipulador de erro que captura qualquer erro gerado durante a execução da Promise.
Exemplo básico com .catch()
Aqui está um exemplo simples de como usar .catch() para capturar erros de uma Promise:
function fetchData() {
return new Promise((resolve, reject) => {
const success = false;
if (success) {
resolve('Dados recebidos com sucesso');
} else {
reject('Falha ao recuperar os dados');
}
});
}
fetchData()
.then(result => {
console.log(result);
})
.catch(err => {
console.error('Erro:', err);
});
Neste código, se a Promise for rejeitada, o erro será capturado no .catch() e exibido no console.
2. Usando async/await para lidar com erros de Promise
O uso de async/await torna o código assíncrono mais fácil de ler e entender. Com async/await, você pode usar a estrutura try/catch para capturar erros de Promessas de maneira mais intuitiva.
Exemplo com async/await e try/catch
Aqui está um exemplo de como usar async/await com try/catch para capturar erros de Promises:
async function fetchData() {
try {
const result = await new Promise((resolve, reject) => {
const success = false;
if (success) {
resolve('Dados recebidos com sucesso');
} else {
reject('Falha ao recuperar os dados');
}
});
console.log(result);
} catch (err) {
console.error('Erro:', err);
}
}
fetchData();
Neste exemplo, a Promise é aguardada usando await, e caso ocorra um erro, ele é capturado pelo catch dentro do try/catch. O uso de async/await torna o código mais legível e mais fácil de debugar.
3. O que fazer quando a Promise não é tratada?
Se uma Promise é rejeitada e o erro não é tratado, o Node.js exibirá um unhandledRejection no console e, eventualmente, o processo será finalizado se não houver tratamento adequado para o erro.
Exemplo de erro não tratado
function fetchData() {
return new Promise((resolve, reject) => {
reject('Falha ao recuperar os dados');
});
}
fetchData(); // Erro não tratado
No exemplo acima, a Promise é rejeitada, mas não há um .catch() ou try/catch para capturar o erro. Isso pode causar falhas no programa.
No Node.js, você pode usar o evento unhandledRejection para capturar erros não tratados globalmente.
process.on('unhandledRejection', (reason, promise) => {
console.error('Erro não tratado:', reason);
process.exit(1); // Finaliza a aplicação após o erro
});
Este código vai capturar rejeições não tratadas de Promises e registrar o erro no console, garantindo que a aplicação não falhe sem uma explicação clara.
4. Rejeições em múltiplas Promises
Quando você tem várias Promises em execução simultânea, é importante garantir que cada Promise tenha seu próprio tratamento de erro. Uma forma comum de lidar com isso é usar Promise.all() para esperar que todas as Promises sejam resolvidas ou rejeitadas.
Exemplo de tratamento de múltiplas Promises com Promise.all():
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => resolve('Dados de promise 1'), 1000);
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => reject('Erro na promise 2'), 1500);
});
Promise.all([promise1, promise2])
.then(results => {
console.log('Resultados:', results);
})
.catch(err => {
console.error('Erro:', err);
});
No exemplo acima, a Promise.all() vai esperar até que todas as Promises sejam resolvidas ou rejeitadas. Se uma das Promises for rejeitada, o erro será capturado no .catch().
5. Conclusão
Lidar com erros de Promise de maneira adequada é essencial para garantir que sua aplicação Node.js seja resiliente e estável. Ao usar .catch() ou try/catch com async/await, você pode garantir que todos os erros sejam capturados e tratados adequadamente, evitando falhas inesperadas.
Além disso, sempre que possível, trate as Promessas rejeitadas globalmente usando o evento unhandledRejection, para evitar que erros não tratados causem problemas em produção.
Como garantir que suas Promises sejam tratadas corretamente no Node.js
As Promises no Node.js são amplamente utilizadas para gerenciar operações assíncronas e garantir que o código continue a execução sem bloqueios. Entretanto, é importante garantir que todos os erros que possam surgir durante a execução dessas Promises sejam adequadamente tratados.
Utilizar try/catch, .catch() e capturar erros globais com unhandledRejection são maneiras eficazes de garantir que a aplicação não falhe sem um tratamento adequado. Usar async/await melhora a legibilidade do código e facilita o tratamento de exceções assíncronas, ajudando a evitar falhas inesperadas no sistema.
Algumas aplicações:
- Testar o comportamento de falhas em requisições HTTP assíncronas.
- Validar consultas a banco de dados e interações com APIs externas.
- Garantir que funções assíncronas não afetem o desempenho da aplicação quando rejeitadas.
- Monitorar erros em tempo real com logs de rejeições de Promises.
- Evitar que o código quebre ao usar Promises em larga escala.
Dicas para quem está começando
- Sempre capture erros de Promises com .catch() ou try/catch para evitar falhas inesperadas.
- Use async/await para escrever código assíncrono de maneira mais legível.
- Registre todas as rejeições de Promises para saber quando e onde ocorreram erros.
- Teste sua aplicação com unit tests para garantir que as Promessas estão sendo resolvidas ou rejeitadas corretamente.
- Evite deixar Promises não tratadas no código de produção, isso pode causar falhas invisíveis.
Contribuições de João Gutierrez