JavaScript

Boas Práticas de Promises em JavaScript: then, catch, finally e Encadeamento para Times Ágeis

7 min de leitura

Boas Práticas de Promises em JavaScript: then, catch, finally e Encadeamento para Times Ágeis

O que é uma Promise? Uma Promise é um objeto JavaScript que representa o resultado eventual (sucesso ou falha) de uma operação assíncrona. Ela funciona como um "contrato": você envia uma tarefa e receberá uma resposta no futuro. Uma Promise pode estar em três estados: pending (aguardando), fulfilled (resolvida com sucesso) ou rejected (rejeitada com erro). As Promises eliminam o "callback hell" e tornam o código assíncrono mais legível e previsível. Quando você cria uma Promise, passa uma função executora com dois parâmetros: (para sucesso) e (para erro). A Promise resolve ou rejeita apenas uma vez, permanecendo naquele estado para sempre. Then, Catch e Finally: Tratando Resultados O método O recebe até dois argumentos: callbacks para sucesso e erro (este último opcional). Retorna uma nova Promise, permitindo encadeamento. Isso é fundamental: cada cria uma nova Promise com o retorno anterior. O método O captura erros em qualquer ponto da cadeia. Ele recebe uma função que trata a rejeição. Usar é

<h2>O que é uma Promise?</h2>

<p>Uma Promise é um objeto JavaScript que representa o resultado eventual (sucesso ou falha) de uma operação assíncrona. Ela funciona como um &quot;contrato&quot;: você envia uma tarefa e receberá uma resposta no futuro. Uma Promise pode estar em três estados: <strong>pending</strong> (aguardando), <strong>fulfilled</strong> (resolvida com sucesso) ou <strong>rejected</strong> (rejeitada com erro).</p>

<pre><code class="language-javascript">const minhaPromise = new Promise((resolve, reject) =&gt; {

setTimeout(() =&gt; {

resolve(&#039;Operação concluída com sucesso!&#039;);

}, 1000);

});

console.log(minhaPromise); // Promise { &lt;pending&gt; }</code></pre>

<p>As Promises eliminam o &quot;callback hell&quot; e tornam o código assíncrono mais legível e previsível. Quando você cria uma Promise, passa uma função executora com dois parâmetros: <code>resolve</code> (para sucesso) e <code>reject</code> (para erro). A Promise resolve ou rejeita apenas uma vez, permanecendo naquele estado para sempre.</p>

<h2>Then, Catch e Finally: Tratando Resultados</h2>

<h3>O método <code>.then()</code></h3>

<p>O <code>.then()</code> recebe até dois argumentos: callbacks para sucesso e erro (este último opcional). Retorna uma <strong>nova Promise</strong>, permitindo encadeamento. Isso é fundamental: cada <code>.then()</code> cria uma nova Promise com o retorno anterior.</p>

<pre><code class="language-javascript">const buscarDados = new Promise((resolve, reject) =&gt; {

setTimeout(() =&gt; {

resolve({ id: 1, nome: &#039;João&#039; });

}, 1000);

});

buscarDados

.then(dados =&gt; {

console.log(&#039;Dados recebidos:&#039;, dados);

return dados.id; // Retorna nova Promise resolvida com o id

})

.then(id =&gt; {

console.log(&#039;ID processado:&#039;, id); // 1

});</code></pre>

<h3>O método <code>.catch()</code></h3>

<p>O <code>.catch()</code> captura erros em qualquer ponto da cadeia. Ele recebe uma função que trata a rejeição. Usar <code>.catch()</code> é a abordagem moderna (preferível ao segundo argumento de <code>.then()</code>).</p>

<pre><code class="language-javascript">const requisicaoFalha = new Promise((resolve, reject) =&gt; {

setTimeout(() =&gt; {

reject(new Error(&#039;Falha na conexão&#039;));

}, 1000);

});

requisicaoFalha

.then(resultado =&gt; console.log(resultado))

.catch(erro =&gt; {

console.error(&#039;Erro capturado:&#039;, erro.message); // Falha na conexão

});</code></pre>

<h3>O método <code>.finally()</code></h3>

<p>O <code>.finally()</code> executa <strong>sempre</strong>, independente de sucesso ou erro. Use-o para limpeza de recursos (fechar conexões, parar spinners de carregamento).</p>

<pre><code class="language-javascript">let carregando = true;

fetch(&#039;https://api.exemplo.com/dados&#039;)

.then(response =&gt; response.json())

.then(dados =&gt; console.log(dados))

.catch(erro =&gt; console.error(erro))

.finally(() =&gt; {

carregando = false;

console.log(&#039;Requisição finalizada&#039;);

});</code></pre>

<h2>Encadeamento de Promises: Composição Poderosa</h2>

<p>Encadeamento significa conectar múltiplas operações assíncronas em sequência. Cada <code>.then()</code> espera o anterior terminar antes de executar. Retornar uma Promise ou um valor comum do <code>.then()</code> permite o próximo na cadeia processar o resultado.</p>

<pre><code class="language-javascript">function buscarUsuario(id) {

return new Promise((resolve) =&gt; {

setTimeout(() =&gt; {

resolve({ id: id, nome: &#039;Ana&#039;, empresaId: 5 });

}, 500);

});

}

function buscarEmpresa(empresaId) {

return new Promise((resolve) =&gt; {

setTimeout(() =&gt; {

resolve({ id: empresaId, nome: &#039;Tech Corp&#039; });

}, 500);

});

}

// Encadeamento

buscarUsuario(1)

.then(usuario =&gt; {

console.log(&#039;Usuário:&#039;, usuario.nome);

return buscarEmpresa(usuario.empresaId); // Retorna nova Promise

})

.then(empresa =&gt; {

console.log(&#039;Empresa:&#039;, empresa.nome);

})

.catch(erro =&gt; console.error(&#039;Algo deu errado:&#039;, erro))

.finally(() =&gt; console.log(&#039;Processo completo&#039;));</code></pre>

<p>Neste exemplo, <code>buscarEmpresa()</code> só executa após <code>buscarUsuario()</code> resolver e retornar o usuário. O encadeamento mantém a ordem e o contexto claros. <strong>Dica importante:</strong> sempre retorne uma Promise ou um valor do <code>.then()</code> se quiser que o próximo acesse esse resultado.</p>

<h2>Padrões Avançados e Boas Práticas</h2>

<p>Ao trabalhar com múltiplas Promises em paralelo (não sequencial), use <code>Promise.all()</code> ou <code>Promise.race()</code>. O <code>Promise.all()</code> espera todas resolverem; o <code>Promise.race()</code> retorna a primeira a resolver ou rejeitar.</p>

<pre><code class="language-javascript">const promise1 = new Promise(resolve =&gt; setTimeout(() =&gt; resolve(&#039;A&#039;), 500));

const promise2 = new Promise(resolve =&gt; setTimeout(() =&gt; resolve(&#039;B&#039;), 1000));

Promise.all([promise1, promise2])

.then(resultados =&gt; {

console.log(resultados); // [&#039;A&#039;, &#039;B&#039;]

});

Promise.race([promise1, promise2])

.then(primeiro =&gt; {

console.log(primeiro); // &#039;A&#039; (a mais rápida)

});</code></pre>

<p><strong>Evite erros comuns:</strong> não coloque <code>.catch()</code> no meio da cadeia sem retornar uma Promise (quebra o fluxo), não esqueça de retornar valores/Promises em <code>.then()</code> se o próximo depender deles, e sempre use <code>.catch()</code> no final ou trate erros adequadamente para evitar rejeições não tratadas.</p>

<h2>Conclusão</h2>

<p>Dominar Promises é essencial para JavaScript moderno. Os três pilares são: <strong><code>.then()</code> para processar sucessos e encadear operações</strong>, <strong><code>.catch()</code> para tratar erros de forma centralizada</strong>, e <strong><code>.finally()</code> para limpeza garantida</strong>. O encadeamento transforma código assíncrono complexo em fluxos legíveis e previsíveis. Pratique combinando essas técnicas em projetos reais — requisições HTTP, manipulação de arquivos, timers — para consolidar o aprendizado.</p>

<h2>Referências</h2>

<ul>

<li><a href="https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Promise" target="_blank" rel="noopener noreferrer">MDN Web Docs - Promise</a></li>

<li><a href="https://javascript.info/promise-basics" target="_blank" rel="noopener noreferrer">JavaScript.info - Promises</a></li>

<li><a href="https://developers.google.com/web/fundamentals/primers/promises" target="_blank" rel="noopener noreferrer">Google Developers - Promises</a></li>

<li><a href="https://eloquentjavascript.net/11_async.html" target="_blank" rel="noopener noreferrer">Eloquent JavaScript - Asynchronous Programming</a></li>

<li><a href="https://github.com/getify/You-Dont-Know-JS" target="_blank" rel="noopener noreferrer">You Don&#039;t Know JS Yet - Async &amp; Performance</a></li>

</ul>

Comentários

Mais em JavaScript

O que Todo Dev Deve Saber sobre Fetch API em JavaScript: Consumindo APIs REST no Navegador
O que Todo Dev Deve Saber sobre Fetch API em JavaScript: Consumindo APIs REST no Navegador

Introdução à Fetch API A Fetch API é a forma moderna e padronizada de fazer r...

Dominando Hooks em React: useState, useEffect, useRef e useCallback em Projetos Reais
Dominando Hooks em React: useState, useEffect, useRef e useCallback em Projetos Reais

useState: Gerenciando Estado em Componentes Funcionais O é o hook fundamental...

Migração de JavaScript para TypeScript em Projetos Existentes: Do Básico ao Avançado
Migração de JavaScript para TypeScript em Projetos Existentes: Do Básico ao Avançado

Preparação e Diagnóstico do Projeto Antes de iniciar qualquer migração, você...