Skip to content

Entendendo e trabalhando com async-await em JavaScript

Códigos assíncronos em JavaScript é sempre um assunto que confunde um pouco, principalmente pra quem está iniciando na linguagem (pelo menos atualmente) vai se deparar com callbacks, promises e agora, com async/await. Todas elas com um mesmo propósito, porém, com abordagens distintas.

Um pouco de contexto

Por muito tempo, devs JavaScript usavam apenas callbacks para trabalhar com códigos assíncronos. Passar funções como argumento – desde que poucas – para outras funções é um conceito muito interessante mas não demorou muito para aparecer uma experiência ruim com o padrão: O callback hell. Se você nunca ouviu falar, dê uma olhada na imagem abaixo e veja essa “maravilha”.

enter image description here

E pra resolver esse problema, veio um recurso novo chamado Promise. Ou seja, uma alternativa melhor em relação aos callbacks e que foi rapidamente adotada!

Uma promise recebe uma função como argumento e esta, por sua vez, recebe mais duas funções, uma para resolver e outra para rejeitar a promise – resolve e reject respectivamente. Como uma Promise implementa a interface thenable, portanto, possui os métodos para resolução e rejeição de uma promise – then e catch.

Vejamos um exemplo:

function func() {
    return new Promise(function(resolve, reject) {
        if(Math.random() < 3) {
            resolve('Promise resolvida');
        } else {
            reject('Promise rejeitada');
        }
    });
}

func()
     .then(result => console.log(result))
     .catch(err => console.log(err));

Ainda não é o cenário ideal, pois ainda precisamos passar funções de callbacks para os métodos then e catch

Códigos assíncronos com Async e Await

Async/Await é uma nova feature lançada na ES8 e que nos permite trabalhar com funções assíncronas de uma forma mais simples e mais fácil de compreender, pois, faz com que os códigos assíncronos tenham o estilo e o comportamento mais parecidos com códigos síncronos.

Vejamos um exemplo:

//Trabalhando com promise
const doSomething = () => {
    getSomething()
        .then(response => response.json())
        .then(data => data);
        .catch(err => err);
}
doSomething();

//Async/Await
const doSomething = async () => {
    const resp = await getSomething();
    return await resp.json();
}
doSomething();

Quando executamos uma instrução precedida por await, a execução da função doSomething() é suspensa até que a promise de getSomething() seja resolvida e o valor retornado é atribuído à variável resp e então a função volta ao seu fluxo de execução.

Async/Await deixam nosso código mais limpo, embora o exemplo acima seja básico, podemos observar que produzimos o mesmo resultado com menos código. Não houve necessidade em escrever métodos then e nem funções de callbacks, bastaram apenas duas keywords.

Vejamos um outro exemplo um pouco mais complexo:

const doSomething = () => {
    return getSomething()
        .then(response => {
           if (response.isThereAnotherRequest) {
             return getSomethingElse(response)
                .then(anotherData => {
                    console.log(anotherData)
                    return anotherData
                });
           } else {
               console.log(response);
               return response;
           }
        });
}


const doSomething = async () => {
    const response = await getSomething();
    if(response.isThereAnotherRequest) {
        const anotherData = await getSomethingElse(response);
        console.log(anotherData)
        return anotherData;
    } else {
        console.log(response);
        return response;
    }
}

Obs: a keyword await só pode ser usada dentro de funções que são assinadas com async. Ou seja, não podemos invocar a função desta forma: await doSomething().

Para manipularmos erros usando promises usamos o método catch. Com async/await basta recorrermos ao bloco try...catch.

const doSomething = async () => {
  try {
    const response = await getSomething();
    return response;
  } catch (err) {
     return err;      
}

Obs: Não é porque temos uma nova forma de trabalharmos com códigos assíncronos usando async-await que você vai deixar as promises de lado, ou até mesmo não conhecer bem seu funcionamento. Até mesmo porque nós continuamos a usar Promises nos “bastidores” de async/await. Por isso é fundamental um bom entendimento sobre o assunto.

Async Await na prática

Preparei um vídeo onde mostro, de forma prática o uso dessas keywords!

Published inArtigosJavaScript