Conceitos Fundamentais
Promises são objetos que representam a eventual conclusão ou falha de uma operação assíncrona. Elas permitem o encadeamento de callbacks de forma mais legível, evitando o "callback hell". O construtor Promise aceita uma função executora com dois argumentos: resolve para sucesso e reject para falha.
Implementação Básica
const minhaPromessa = new Promise((resolucao, rejeicao) => {
// Exemplo condicional
const condicao = Math.random() > 0.5;
if (condicao) {
resolucao('Operação bem-sucedida');
} else {
rejeicao('Erro na operação');
}
});
minhaPromessa.then(
resultado => console.log(resultado),
erro => console.error(erro)
);
Casos de Uso Iniciais
1. Leitura de Arquivos com Módulo fs
const fs = require('fs');
const caminhoArquivo = './dados.txt';
function lerArquivoComPromessa(caminho) {
return new Promise((sucesso, falha) => {
fs.readFile(caminho, 'utf8', (erro, conteudo) => {
if (erro) falha(erro);
else sucesso(conteudo);
});
});
}
lerArquivoComPromessa(caminhoArquivo)
.then(dados => console.log('Conteúdo:', dados))
.catch(err => console.error('Erro:', err));
2. Requisição Ajax com XMLHttpRequest
<html>
<head>
<title>Exemplo Ajax com Promise</title>
</head>
<body>
<button id="btnSolicitar">Carregar Dados</button>
<script>
document.getElementById('btnSolicitar').addEventListener('click', () => {
const promessaAjax = new Promise((resolver, rejeitar) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.exemplo.com/dados');
xhr.onload = () => {
if (xhr.status >= 200 && xhr.status < 300) {
resolver(xhr.responseText);
} else {
rejeitar(new Error(`Status: ${xhr.status}`));
}
};
xhr.onerror = () => rejeitar(new Error('Erro de rede'));
xhr.send();
});
promessaAjax
.then(dados => console.log('Resposta:', dados))
.catch(err => console.error('Falha:', err));
});
</script>
</body>
</html>
3. Função Genérica para Ajax
function obterDados(url) {
return new Promise((aceitar, recusar) => {
const conexao = new XMLHttpRequest();
conexao.open('GET', url);
conexao.onload = function() {
this.status >= 200 && this.status < 300
? aceitar(this.response)
: recusar(this.status);
};
conexao.send();
});
}
obterDados('https://api.exemplo.com/info').then(console.log).catch(console.error);
Conversão para Estilo Promise
O módulo util do Node.js oferece promisify para transformar funções com callback de erro em versões baseaads em Promises.
const util = require('util');
const fs = require('fs');
const lerArquivoPromisificado = util.promisify(fs.readFile);
lerArquivoPromisificado('./config.json', 'utf8')
.then(conteudo => console.log(JSON.parse(conteudo)))
.catch(erro => console.error('Falha na leitura:', erro));
Propriedades de uma Promise
- Estado (PromiseState): Pode ser
pendente,resolvidaourejeitada. - Resultado (PromiseResult): Armazena o valor da resolução ou o motivo da rejeição.
API de Promises
new Promise(executor): Executor é chamado imediatamente de forma síncrona.Promise.prototype.then(onFulfilled, onRejected): Retorna uma nova Promise.Promise.prototype.catch(onRejected): Atalho para tratar rejeições.Promise.resolve(valor): Cria uma Promise resolvida. Sevalorfor uma Promise, retorna-a.Promise.reject(razao): Cria uma Promise rejeitdaa com o valor fornecido.Promise.all(iteravel): Resolve quando todas as Promises no iterável resolvem. Rejeita na primeira rejeição.Promise.race(iteravel): Resolve ou rejeita com o resultado da primeira Promise a mudar de estado.
Tópicos Avançados e Perguntas Comuns
Alterando Estados de uma Promise
Uma Promise pode ter seu estado alterado por: chamada de resolve, chamada de reject ou lançamento de um erro dentro do executor.
Múltiplos Callbacks em uma Promise
const promessaMultipla = new Promise(resolve => resolve('valor'));
promessaMultipla.then(v => console.log('Callback 1:', v));
promessaMultipla.then(v => console.log('Callback 2:', v));
// Ambos os callbacks são executados
Encadeamento de Operações
const tarefaAssincrona = () => new Promise(resolve =>
setTimeout(() => resolve('Passo 1 concluído'), 100)
);
tarefaAssincrona()
.then(msg => {
console.log(msg);
return new Promise(resolve => resolve('Passo 2'));
})
.then(resultado => console.log(resultado))
.then(() => console.log('Passo 3')); // Resultado undefined se não houver retorno
Propagação de Erros
Em uma cadeia de then, erros são capturados pelo próximo catch ou tratamento de rejeição.
Interrompendo a Cadeia
Retorne uma Promise pendente dentro de um then para pausar o encadeamento:
function processarDados() {
return new Promise(() => {}); // Promise pendente
}
Promise.resolve('inicio')
.then(processarDados)
.then(() => console.log('Isso não será executado'));