JavaScript

Dominando Async e Await em JavaScript: Código Assíncrono com Aparência Síncrona em Projetos Reais

6 min de leitura

Dominando Async e Await em JavaScript: Código Assíncrono com Aparência Síncrona em Projetos Reais

O Problema das Callbacks e Promises Antes de entender async/await, você precisa conhecer o contexto. JavaScript executa código de forma assíncrona naturalmente — operações como requisições HTTP, leitura de arquivos e timers não bloqueiam a execução. Historicamente, usávamos callbacks para lidar com essas operações, mas isso levava ao famoso "callback hell": código aninhado, difícil de ler e manter. As Promises vieram como solução, permitindo uma sintaxe mais limpa com e , mas ainda não era intuitivo como código síncrono. Entendendo Async/Await Async/await é açúcar sintático sobre Promises que permite escrever código assíncrono com aparência síncrona. Uma função sempre retorna uma Promise, e a palavra-chave pausa a execução até que uma Promise seja resolvida. Isso torna o fluxo de controle muito mais legível e intuitivo para quem está acostumado com programação síncrona tradicional. A função , e retornam Promises. O pausa a execução até que cada uma seja resolvida, e o resultado é atribuído diretamente à variável. Se alguma Promise for

<h2>O Problema das Callbacks e Promises</h2>

<p>Antes de entender async/await, você precisa conhecer o contexto. JavaScript executa código de forma assíncrona naturalmente — operações como requisições HTTP, leitura de arquivos e timers não bloqueiam a execução. Historicamente, usávamos callbacks para lidar com essas operações, mas isso levava ao famoso &quot;callback hell&quot;: código aninhado, difícil de ler e manter. As Promises vieram como solução, permitindo uma sintaxe mais limpa com <code>.then()</code> e <code>.catch()</code>, mas ainda não era intuitivo como código síncrono.</p>

<pre><code class="language-javascript">// Callback Hell (difícil de ler)

fetchUser(userId, function(err, user) {

if (err) console.error(err);

fetchPosts(user.id, function(err, posts) {

if (err) console.error(err);

fetchComments(posts[0].id, function(err, comments) {

console.log(comments);

});

});

});

// Com Promises (melhor, mas ainda verboso)

fetchUser(userId)

.then(user =&gt; fetchPosts(user.id))

.then(posts =&gt; fetchComments(posts[0].id))

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

.catch(err =&gt; console.error(err));</code></pre>

<h2>Entendendo Async/Await</h2>

<p>Async/await é açúcar sintático sobre Promises que permite escrever código assíncrono com aparência síncrona. Uma função <code>async</code> sempre retorna uma Promise, e a palavra-chave <code>await</code> pausa a execução até que uma Promise seja resolvida. Isso torna o fluxo de controle muito mais legível e intuitivo para quem está acostumado com programação síncrona tradicional.</p>

<pre><code class="language-javascript">// Agora a mesma lógica é clara e linear

async function processUserData(userId) {

try {

const user = await fetchUser(userId);

const posts = await fetchPosts(user.id);

const comments = await fetchComments(posts[0].id);

console.log(comments);

} catch (err) {

console.error(err);

}

}

// Chamar uma função async

processUserData(1);</code></pre>

<p>A função <code>fetchUser</code>, <code>fetchPosts</code> e <code>fetchComments</code> retornam Promises. O <code>await</code> pausa a execução até que cada uma seja resolvida, e o resultado é atribuído diretamente à variável. Se alguma Promise for rejeitada, o bloco <code>catch</code> intercepta o erro. Isso é muito mais legível do que encadear múltiplos <code>.then()</code>.</p>

<h2>Padrões Avançados e Armadilhas Comuns</h2>

<h3>Paralelismo vs. Sequência</h3>

<p>Um erro comum é usar <code>await</code> desnecessariamente em sequência quando operações podem rodar em paralelo. Se você tem duas requisições independentes, executá-las em série é ineficiente. Use <code>Promise.all()</code> para operações que não dependem uma da outra.</p>

<pre><code class="language-javascript"></code></pre>

<h3>Tratamento de Erros</h3>

<p>O <code>try/catch</code> é o padrão recomendado, mas você pode também encadear <code>.catch()</code> em uma Promise. Para erros em múltiplas operações paralelas, <code>Promise.all()</code> rejeita assim que uma falha, enquanto <code>Promise.allSettled()</code> espera todas terminarem (sucesso ou falha).</p>

<pre><code class="language-javascript">// Promise.allSettled aguarda todas as operações

async function tratarMultiplosErros() {

const resultados = await Promise.allSettled([

fetchUser(1),

fetchUser(2),

fetchUser(999) // vai falhar

]);

resultados.forEach((resultado, index) =&gt; {

if (resultado.status === &#039;fulfilled&#039;) {

console.log(User ${index}:, resultado.value);

} else {

console.log(User ${index} falhou:, resultado.reason);

}

});

}</code></pre>

<h3>Loops Assíncrono</h3>

<p>Quando você precisa iterar sobre um array e aguardar operações dentro do loop, cuidado: <code>forEach()</code> não aguarda promises. Use <code>for...of</code> ou <code>.reduce()</code> para controlar a sequência.</p>

<pre><code class="language-javascript"></code></pre>

<h3>Funções Auxiliares: Implementação Real</h3>

<pre><code class="language-javascript">// Simular requisições HTTP (para teste)

function fetchUser(id) {

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

setTimeout(() =&gt; {

if (id &gt; 0) {

resolve({ id, name: User ${id} });

} else {

reject(new Error(&#039;ID inválido&#039;));

}

}, 1000);

});

}

// Usar em uma aplicação real

async function main() {

try {

const user = await fetchUser(1);

console.log(&#039;Usuário encontrado:&#039;, user);

const multiplos = await Promise.all([

fetchUser(1),

fetchUser(2),

fetchUser(3)

]);

console.log(&#039;Múltiplos usuários:&#039;, multiplos);

} catch (err) {

console.error(&#039;Erro:&#039;, err.message);

}

}

main();</code></pre>

<h2>Conclusão</h2>

<p>Async/await revoluciona a forma como lidamos com código assíncrono em JavaScript, tornando-o tão legível quanto síncrono. <strong>Primeiro aprendizado:</strong> sempre prefira async/await sobre callbacks e evite o excesso de <code>.then()</code> — o código fica mais limpo e fácil de manter. <strong>Segundo aprendizado:</strong> lembre-se que <code>await</code> pausa a execução, então use <code>Promise.all()</code> quando operações são independentes para não desperdiçar performance. <strong>Terceiro aprendizado:</strong> dominando loops assíncrono e tratamento de erros com <code>try/catch</code>, você terá total controle sobre fluxos complexos de dados e requisições.</p>

<h2>Referências</h2>

<ul>

<li><a href="https://developer.mozilla.org/pt-BR/docs/Learn_web_development/Extensions/Async_JS/Promises" target="_blank" rel="noopener noreferrer">MDN Web Docs - Async/await</a></li>

<li><a href="https://javascript.info/async-await" target="_blank" rel="noopener noreferrer">JavaScript.info - Async/await</a></li>

<li><a href="https://tc39.es/ecma262/#sec-async-function-definitions" target="_blank" rel="noopener noreferrer">ECMAScript Specification - Async Function</a></li>

<li><a href="https://nodejs.org/en/docs/guides/blocking-vs-non-blocking/" target="_blank" rel="noopener noreferrer">Node.js Official Docs - Asynchronous</a></li>

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

</ul>

Comentários

Mais em JavaScript

Higher-Order Functions em JavaScript: map, filter, reduce e Composição na Prática
Higher-Order Functions em JavaScript: map, filter, reduce e Composição na Prática

O que são Higher-Order Functions? Higher-Order Functions (HOF) são funções qu...

Streams em Node.js: Leitura, Escrita e Transformação de Dados: Do Básico ao Avançado
Streams em Node.js: Leitura, Escrita e Transformação de Dados: Do Básico ao Avançado

Entendendo Streams: A Base Conceitual Streams são sequências contínuas de dad...

Eventos no DOM: addEventListener, Delegação e Propagação: Do Básico ao Avançado
Eventos no DOM: addEventListener, Delegação e Propagação: Do Básico ao Avançado

addEventListener: Fundamentos e Sintaxe O método é a forma moderna e recomend...