O que é async/await e como funciona?
Em JavaScript, o uso de funções assíncronas é muito comum para realizar tarefas como requisições de rede ou manipulação de grandes volumes de dados sem bloquear a execução do código. Uma das maneiras mais modernas e eficientes de lidar com funções assíncronas é usando async
e await
. Eles são baseados em Promises e ajudam a tornar o código assíncrono mais legível e mais fácil de escrever. Neste tutorial, vamos entender o que são async
e await
, como usá-los e como eles podem simplificar o seu código.
O que é async
?
A palavra-chave async
é usada para declarar uma função como assíncrona, o que significa que ela sempre retornará uma Promise. Mesmo que você não use explicitamente uma Promise dentro da função, o JavaScript irá automaticamente envolver o valor retornado em uma Promise. Isso permite usar o await
dentro da função para esperar pela resolução de uma Promise.
Exemplo básico de uma função assíncrona com async
:
async function minhaFuncao() {
return 'Resultado';
}
minhaFuncao().then(result => console.log(result)); // 'Resultado'
Neste exemplo, a função minhaFuncao
é declarada como async
, e ela retorna uma Promise que resolve o valor 'Resultado'. O uso do then()
fora da função demonstra como a Promise é resolvida.
O que é await
?
A palavra-chave await
só pode ser usada dentro de funções async
. Ela faz com que o JavaScript espere pela resolução de uma Promise antes de continuar a execução do código na linha seguinte. Isso faz com que o código assíncrono pareça síncrono, tornando-o muito mais legível.
Exemplo de uso do await
para esperar a resolução de uma Promise:
async function minhaFuncao() {
let resultado = await novaPromise();
console.log(resultado); // 'Operação concluída'
}
function novaPromise() {
return new Promise(resolve => {
setTimeout(() => resolve('Operação concluída'), 1000);
});
}
Neste exemplo, a função novaPromise
retorna uma Promise que é resolvida após 1 segundo. A palavra-chave await
faz com que a execução de minhaFuncao
seja pausada até que a Promise seja resolvida, e o resultado é então impresso no console.
Explicação do código acima
- A função
minhaFuncao
é assíncrona e utiliza oawait
para esperar a resolução da Promise retornada pornovaPromise
. - O código dentro de
minhaFuncao
só prossegue quando a Promise é resolvida, o que torna o código muito mais fácil de entender em comparação com o uso de callbacks ou encadeamento de.then()
.
Como async/await
melhora o código assíncrono
Um dos maiores benefícios do async/await
é que ele permite escrever código assíncrono de uma maneira mais sequencial e parecida com o código síncrono. Isso torna o código muito mais fácil de ler, entender e depurar. Além disso, você pode combinar async/await
com o uso de Promises para realizar múltiplas operações assíncronas em sequência ou em paralelo.
Exemplo de encadeamento de várias Promises com async/await
:
async function executarOperacoes() {
try {
let resultado1 = await operacao1();
let resultado2 = await operacao2(resultado1);
console.log('Resultados:', resultado1, resultado2);
} catch (error) {
console.log('Erro:', error);
}
}
async function operacao1() {
return 'Primeiro resultado';
}
async function operacao2(result1) {
return result1 + ' + Segundo resultado';
}
executarOperacoes();
Neste exemplo, as operações são realizadas uma após a outra, de forma simples e legível. O uso de try/catch
permite o tratamento de erros de maneira centralizada, sem a necessidade de múltiplos manipuladores de erros.
Quando não usar await
?
Embora o await
seja muito útil, você deve ter cuidado ao usá-lo em loops ou em situações onde várias operações assíncronas precisam ser executadas em paralelo. Quando você usa await
dentro de um loop, o JavaScript irá esperar a conclusão de cada operação antes de passar para a próxima, o que pode resultar em uma execução mais lenta do que o necessário.
Exemplo de código que pode ser otimizado:
async function processarDados() {
let resultados = [];
for (let i = 0; i < 5; i++) {
resultados.push(await buscarDados(i));
}
console.log(resultados);
}
async function buscarDados(id) {
return new Promise(resolve => setTimeout(() => resolve(id), 1000));
}
processarDados();
Aqui, o código está esperando que cada chamada à função buscarDados
seja concluída antes de continuar para a próxima. Para otimizar isso, podemos usar Promise.all()
para executar todas as operações em paralelo.
Usando Promise.all()
com async/await
async function processarDados() {
let resultados = await Promise.all([
buscarDados(0),
buscarDados(1),
buscarDados(2),
buscarDados(3),
buscarDados(4)
]);
console.log(resultados);
}
Com Promise.all()
, todas as Promises são iniciadas ao mesmo tempo, e o código aguarda que todas sejam resolvidas antes de continuar. Isso melhora o desempenho, especialmente quando você está lidando com múltiplas operações independentes.
Conclusão
async/await
é uma poderosa ferramenta em JavaScript que facilita o trabalho com código assíncrono. Ao usá-la, você pode escrever código mais legível e sequencial, sem a necessidade de encadeamentos complexos de Promises ou callbacks. O await
permite que você "pausa" a execução até que uma Promise seja resolvida, enquanto o async
transforma funções em Promises. Usar essas ferramentas de forma eficaz pode melhorar significativamente a qualidade e legibilidade do seu código.
Por que usar async/await para escrever código assíncrono mais legível
O uso de async/await
revoluciona o desenvolvimento com JavaScript, simplificando o código assíncrono e permitindo que ele se pareça com código síncrono. Isso não só melhora a legibilidade, mas também facilita o tratamento de erros e o encadeamento de operações. No entanto, é importante entender quando usar await
e quando outras abordagens, como Promise.all()
, podem ser mais eficientes.
Algumas aplicações:
- Facilitar a escrita e o entendimento de código assíncrono em JavaScript.
- Substituir o uso de callbacks aninhados, tornando o código mais legível e fácil de depurar.
- Permitir que múltiplas operações assíncronas sejam executadas de forma sequencial e simples.
- Utilizar com
Promise.all()
para executar várias Promises em paralelo, otimizando o desempenho do código.
Dicas para quem está começando
- Comece com exemplos simples de
async
eawait
antes de passar para usos mais complexos. - Entenda o fluxo de execução de código assíncrono com
async/await
e como ele pode ser mais intuitivo do que o encadeamento de Promises. - Pratique o uso de
try/catch
para capturar erros em funções assíncronas e garantir que seu código seja robusto. - Evite usar
await
em loops quando várias operações puderem ser feitas em paralelo, usePromise.all()
para otimizar.
Contribuições de Fernando Antunes