async/await
Nesta aula, você aprenderá a sintaxe do async/await em JavaScript, como tratar erros com try/catch e a diferença entre execução sequencial e paralela de promises. O conteúdo inclui exemplos práticos, boas práticas e exercícios com respostas.
Nesta aula, vamos explorar o async/await, uma sintaxe moderna do JavaScript que simplifica o trabalho com promises. Introduzido no ES2017, ele permite escrever código assíncrono de forma síncrona, melhorando a legibilidade e a manutenção. Você aprenderá como declarar funções assíncronas, usar await para aguardar promises, tratar erros com try/catch e decidir quando executar operações em sequência ou em paralelo.
O async/await é construído sobre promises, mas elimina a necessidade de encadeamento com .then() e .catch(). Uma função marcada com async sempre retorna uma promise, e o await pausa a execução até que a promise seja resolvida.
Sintaxe
Para usar async/await, você declara uma função com a palavra-chave async antes de function. Dentro dela, use await antes de uma promise para esperar sua resolução. O valor resolvido da promise é retornado diretamente.
Exemplo básico:
function esperar(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function saudacao() {
console.log('Olá');
await esperar(1000);
console.log('Mundo!');
}
saudacao();
// Saída: Olá (após 1 segundo) Mundo!Note que await só pode ser usado dentro de funções async. No módulo ES, você pode usar await no topo de módulos (top-level await).
Tratamento de erro com try/catch
Erros em funções assíncronas podem ser capturados com try/catch, similar ao código síncrono. Se uma promise for rejeitada dentro do bloco try, o controle vai para o catch.
Exemplo:
async function buscarDados() {
try {
const resposta = await fetch('https://api.exemplo.com/dados');
if (!resposta.ok) {
throw new Error('Erro na requisição: ' + resposta.status);
}
const dados = await resposta.json();
console.log(dados);
} catch (erro) {
console.error('Erro capturado:', erro.message);
}
}
buscarDados();Você também pode usar finally para executar código independentemente de sucesso ou erro, como limpar recursos.
Sequencial vs paralelo
Quando você usa await em cada promise, a execução é sequencial: a próxima operação só começa após a anterior terminar. Isso é útil quando há dependência entre elas.
Exemplo sequencial:
async function sequencial() {
const a = await Promise.resolve(10);
const b = await Promise.resolve(20);
return a + b;
}
// Demora o tempo da soma das duas promisesPara executar em paralelo, use Promise.all (ou Promise.allSettled, Promise.race) para iniciar várias promises simultaneamente e aguardar todas com um único await.
Exemplo paralelo:
async function paralelo() {
const [a, b] = await Promise.all([
Promise.resolve(10),
Promise.resolve(20)
]);
return a + b;
}
// Demora apenas o tempo da promise mais lentaEscolha entre sequencial e paralelo com base na lógica do seu programa. Se as operações são independentes, o paralelo é mais eficiente.
Boas práticas
Evite usar await dentro de loops forEach; prefira for...of com await ou Promise.all com map. Sempre trate erros em funções assíncronas, seja com try/catch ou encadeando .catch(). Lembre-se de que funções async sempre retornam uma promise, então você pode usar then/catch externamente se necessário.
Referências
- MDN: async function
- MDN: await
- MDN: Promise.all
- JavaScript.info: Async/await
- W3Schools: JavaScript Async
Exercícios
Crie uma função assíncrona chamada
obterUsuarioque recebe um id e retorna um objeto usuário simulado após 1 segundo. UsesetTimeoutcom promise. Em seguida, chame a função e exiba o resultado no console.✓ Resposta:function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } async function obterUsuario(id) { await delay(1000); return { id, nome: 'João', email: 'joao@exemplo.com' }; } obterUsuario(1).then(console.log); // ou (async () => console.log(await obterUsuario(1)))();Escreva uma função assíncrona
dividirque recebe dois números e retorna a divisão, mas rejeita a promise se o divisor for zero. Usetry/catchpara capturar o erro e exibir uma mensagem amigável.✓ Resposta:async function dividir(a, b) { if (b === 0) { throw new Error('Divisão por zero'); } return a / b; } (async () => { try { const resultado = await dividir(10, 2); console.log(resultado); // 5 const erro = await dividir(10, 0); } catch (erro) { console.error('Erro:', erro.message); } })();Você tem duas funções assíncronas:
tarefaAque leva 2 segundos etarefaBque leva 3 segundos. Escreva código para executá-las em paralelo e exibir o tempo total aproximado (useconsole.timeeconsole.timeEnd).✓ Resposta:function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } async function tarefaA() { await delay(2000); return 'A'; } async function tarefaB() { await delay(3000); return 'B'; } async function executar() { console.time('paralelo'); const [resultadoA, resultadoB] = await Promise.all([tarefaA(), tarefaB()]); console.timeEnd('paralelo'); // ~3 segundos console.log(resultadoA, resultadoB); } executar();Converta o seguinte código baseado em promises encadeadas para usar
async/awaitcomtry/catch:function buscarDados() { return fetch('https://api.exemplo.com/dados') .then(resposta => resposta.json()) .then(dados => console.log(dados)) .catch(erro => console.error(erro)); }✓ Resposta:async function buscarDados() { try { const resposta = await fetch('https://api.exemplo.com/dados'); const dados = await resposta.json(); console.log(dados); } catch (erro) { console.error(erro); } }Escreva uma função assíncrona
processarItensque recebe um array de URLs e faz o download de cada uma em paralelo, mas com um limite de 2 requisições simultâneas. UsePromise.allem lotes. Dica: você pode usar um loop ou uma biblioteca, mas tente implementar manualmente.✓ Resposta:async function processarItens(urls) { const limite = 2; const resultados = []; for (let i = 0; i < urls.length; i += limite) { const lote = urls.slice(i, i + limite); const promises = lote.map(url => fetch(url).then(res => res.json())); const dados = await Promise.all(promises); resultados.push(...dados); } return resultados; } // Exemplo de uso: // const urls = ['url1', 'url2', 'url3', 'url4']; // processarItens(urls).then(console.log);