Entenda o async e await

Async e await são extensões das promises. Caso você não conheça promises, acesse o artigo seguinte e realize a leitura antes de prosseguir com async e await: https://www.mundojs.com.br/2020/03/02/o-que-sao-e-como-criar-promises/.

Quando uma função assíncrona é chamada, ela retorna uma promise. Uma função assíncrona pode conter uma palavra-chave await, que pausa a execução da função e espera pela resolução da promise passada, retomando a execução após a resolução da promise e retornando o valor resolvido.

A proposta das funções async/await é simplificar o uso de promises. Assim como promises são similares a callbacks estruturados, as funções async/await são similares à junção de generators com promises.

async:

A palavra async antes de uma função significa que a função sempre retorna uma promise. Outros valores serão agrupados em uma promise resolvida automaticamente. Por exemplo, esta função async retorna uma promise resolved com a string “Ola Mundo”:

async function funcaoAsync() {
    return 'Ola Mundo';
}

funcaoAsync().then(console.log);

E nós podemos retornar uma promise explicitamente, que retornaria a mesma coisa:

async function funcaoAsync(){
    return Promise.resolve('Ola Mundo')
}

funcaoAsync().then(console.log);

Então, o async garante que a função retorne uma promise.

Mas há outra palavra-chave, chamada await, que funciona apenas dentro de funções assíncronas.

await:

A palavra-chave await faz com que a função espere até que a promise seja estabelecida e retorne o seu resultado. Confira neste exemplo o seu funcionamento:

async function funcaoAsyncAwait() {
    // Criaremos uma promise que retornará a string 
    // "Promise concluída", após o tempo de 5 segundos.
    let promise = new Promise((resolve, reject) => {
        setTimeout(() => resolve("Promise concluída!"), 5000)
    });

    // Esta variavel resultado recebe o resultado da promise, após sua conclusão.
    let resultado = await promise;
    console.log(resultado);
}

funcaoAsyncAwait();

Nesta função, a execução “pausa” e somente retorna quando passa o tempo de execução da promise. Literalmente falando, o await aguarda a conclusão da promise para retornar o resultado! Então, você verá a string “Promise concluída” após 5 segundos de execução, que é o tempo que estabelecemos para a conclusão da promise.

Observação: Não podemos utilizar o await em função síncronas. Ele funciona somente em funções assíncronas, então, precisamos ter o async em nossa function.

Manipulando erros:

Se a promise for resolvida normalmente, aguardamos o retorno do resultado. Mas e no caso de uma rejeição, que geraria um erro, como agiremos?

async function asyncError1() {
    await Promise.reject(new Error("Erro!"));
}

asyncError1();

Podemos utilizar a palavra-chave throw, que funcionará da mesma forma:

async function asyncError1() {
    throw new Error("Erro!");
}

asyncError1();

Em situações reais, a promise pode levar algum tempo até ser rejeitada. Nesse caso, haverá um delay antes do await lançar um erro. Podemos detectar esse erro usando try…catch, da mesma maneira que um throw normal:

async function asyncTryCatch() {
    try {
        let response = await fetch('http://nenhuma-url-aqui');
    } catch(err) {
        console.log(err);
    }
}

asyncTryCatch();

No caso de erro, o código passará para o bloco catch. Também podemos agrupar várias linhas:

async function asyncTryCatch() {
    try {
        let response = await fetch('/nenhum-usuario-aqui');
        let usuario = await response.json();
    } catch(err) {
        console.log(err);
    }
}

asyncTryCatch();

Se não temos um try…catch, a promise gerada pela chamada da função async será rejeitada. podemos utilizar o .catch para lidar com isso:

async function asyncCatch() {
        let response = await fetch('http://nenhuma-url-aqui');   
}
// asyncCatch() será uma promise rejeitada
asyncCatch().catch(console.log);

Se não adicionarmos o .catch, obteremos um erro de promise não tratada.

Então é isso pessoal. Gostaram do artigo? Comente abaixo:

Referências: