Ir para o conteúdo
Angular Async/Await: Por que você precisava dele e como usá-lo

Angular Async/Await: Por que você precisava dele e como usá-lo

O que é Async Await em Angular e como usá-lo para evitar o inferno de retorno de chamada? Aprenda as respostas em nosso artigo mais recente

6min read

Angular é uma ótima estrutura, mas escrever código assíncrono e fazer chamadas assíncronas é difícil. Especialmente se você não conseguir decidir entre Async/Await e Angular Promise. Portanto, neste tutorial, vou ajudá-lo a entender as diferenças entre Async/Await e Promise por meio de exemplos e trechos de código. Também explicarei como você pode facilmente evitar o inferno de retorno de chamada e demonstrarei como usar Async/Await em JavaScript com a ajuda de Ignite UI for Angular Components.

Try Ignite UI for Angular

O que é código assíncrono no Angular?

Quando falamos de código assíncrono, queremos dizer simplesmente que o código não é executado sequencialmente e o processo envolve multithreading. É uma forma de programação paralela que executa um bloco de código separado sem quebrar o thread principal do aplicativo. A execução de código assíncrono é útil no caso de grandes iterações ou quando você tem operações complexas.

Mas se você busca simplicidade e operações de curta duração para seu aplicativo Angular, é melhor evitar a programação assíncrona. Normalmente, o código assíncrono é mais difícil de ler, portanto, qualquer coisa que possa melhorar sua legibilidade e torná-lo mais simples para os desenvolvedores é considerada um impulsionador da qualidade. E o JavaScript tem seus próprios truques e mecanismos para lidar com isso.

How JavaScript Handles Asynchronous Code

Por padrão, o JavaScript é uma linguagem síncrona de thread único, executando uma instrução por vez, de cima para baixo. Isso significa que novos threads e processos não podem executar código em paralelo ao fluxo principal do programa. Ele tem uma pilha de chamadas e uma memória heap e executa o código em ordem e deve terminar de executar um pedaço de código antes de passar para o próximo. Tudo acontece sequencialmente. Mas o que acontece quando, por exemplo, você deve fazer várias chamadas AJAX em uma única página?

A primeira solução que vem à mente é o uso de retornos de chamada. Mas eles levam a um grande problema conhecido pelos programadores como "inferno de retorno de chamada". Essencialmente, essa é uma estrutura de código aninhada e promissora que requer a realização de várias solicitações e transformações de dados, muitas vezes resultando em código difícil de manter e ler e um aplicativo menos escalonável.

Acontece que os retornos de chamada não são a melhor maneira de lidar com o código assíncrono para seu aplicativo Angular. E então? Talvez Angular promessa? Esse padrão encapsula com eficiência as operações assíncronas e notifica quando elas são concluídas. No entanto, embora forneça um código mais limpo e de fácil manutenção, usar Angular Promise não é a solução ideal, pois, muitas vezes, ele reutiliza o mesmo código repetidamente, contradizendo o principle.cl DRY (Don't Repeat Yourself)

Felizmente, temos Async/Await em Angular.

Using Async/Await in Angular

Uma das melhores melhorias em JavaScript é o recurso Async/Await introduzido no ECMAScript 7. Basicamente, Async/Await funciona em cima do Promise e permite que você escreva código assíncrono de maneira síncrona. Ele simplifica o código e torna o fluxo e a lógica mais compreensíveis.

Observe que, como ele não usa mais o encadeamento then e catch, você pode lidar com erros executando try/catch.

Async/Await vs Promise: Qual é a diferença?

Para apresentar as diferenças entre Async/Await e promises, vamos fazer uma tabela para compará-las de uma forma mais digerível e concisa.

Promise 

Async/Await 

Promise é uma operação que tem a garantia de concluir sua execução em algum momento no futuro

Async/Await é construído com base em promessas. Eles são açúcar sintático para promessas, fazendo com que o código pareça mais síncrono

O tratamento de erros é feito usando os métodos .then() e catch()

O tratamento de erros é feito usando os métodos try() e catch()

Às vezes, pode ser difícil entender as cadeias de promessas

Async e await facilitam a leitura e a compreensão do fluxo do programa no código

Tem 3 estados – pendentes, resolvidos e rejeitados

Ele retorna uma promessa resolvida ou rejeitada

Vamos criar um exemplo com ambas as sintaxes em uma Angular Grade de Dados e ver as diferenças. Temos uma função que está fazendo duas chamadas assíncronas para uma API, uma para obter dados do usuário e outra para obter clubes nos quais os usuários são membros. A segunda chamada depende da primeira, o que significa que getUserData() deve ser concluída antes de prosseguir com a outra solicitação. Ambas as sintaxes são fáceis de ler, mas é claro que usar promessas com .then() e .catch() pode levar ao inferno de retorno de chamada, o que torna o código difícil de entender e manter.

const makeRequest = () =>
     getUserData()
    . then(user => getClubsForUser(user.id))
    .then(console.log)
    .catch(err => console.log('Error: ' + err.message));
const makeRequest = async () => {
    try {
        let user = await getUserData();
        let clubs = await getClubsForUser(user.id);
        console.log(clubs);
     }
    catch(err) {
        console.log(err.message);
   }
};

 

Como usar o Async/Await no Angular com Ignite UI

Vamos criar uma função que obterá dados do usuário de uma entrada de formulário e, em seguida, fará uma solicitação a uma API para verificar se as credenciais do usuário estão corretas e, em caso afirmativo, redirecionará para a página inicial. Usar Async/Await no Ignite UI for Angular pode nos ajudar nessa situação. Temos uma solicitação para uma API que é uma operação assíncrona e é por isso que usaremos await para ela e, se não houver outros problemas, salvaremos os dados.

const submitLoginData = async () => { 
    try { 
         if (this.userInput.email && this.userInput.password) { 
         const response = await this.loginUser(this.userInput); 

         if (response.statusCode === 200) { 
             alert('User is successfully logged in!'); 
             await saveUserData(response.data); 
             this.router.navigate(['/']); 
         } 
         else { 
             alert(response.message); 
             this.router.navigate(['/login']); 
         }
     } 
   } 
     .catch(err) { 
         alert('Something went wrong, try again later!') 
         this.router.navigate(['/login']); 
     } 
} 

Definitivamente, podemos usar .then() e .catch() aqui, mas Async/Await em Ignite UI for Angular torna o código mais elegante. Cabe à pessoa que está escrevendo o código escolher qual sintaxe usar. Mas também, é recomendável aderir a uma abordagem, pois misturar estilos pode tornar o código complicado.

Async/Await Angular Best Practices

Quando estamos usando async e await para lidar com código assíncrono, devemos sempre colocar nosso código no bloco try/catch. Dessa forma, garantiremos que, mesmo que a promessa esteja gerando um erro, ela será detectada e processada corretamente.

async function loadComponents() {
     try {
         this.components = await fetchComponentsByType('charts');
     }
     .catch(err) {
         logger.error(err);
     }
}

Com Ignite UI, não precisamos retornar explicitamente uma promessa em uma função assíncrona. Na verdade, uma função assíncrona sempre retorna uma Promise. O que significa que a criação de uma Promise dentro de uma função assíncrona apenas adiciona sobrecarga de desempenho ao nosso aplicativo Angular.

async function loadChartSelectors() {
     return Promise.resolve(['igx-data-chart', 'igx-pie-chart', 'igx-category-chart']);
}

Resumo

As palavras-chave Async/Await facilitam a leitura e a depuração do código. No entanto, se quisermos usá-los corretamente, devemos entender como as promessas funcionam em geral, porque, como dissemos, elas não são mais do que açúcar sintático para promessas.

Ignite UI Angular

Solicite uma demonstração