Skip to content

O que é async await em JavaScript?

Introdução

Funções assíncronas usam a sintaxe async e await para esperar que uma promise seja resolvida. Para entender melhor este artigo, é recomendado saber como as promises funcionam. Você pode aprender sobre elas aqui.

Callback hell

Uma das razões pelas quais async/await foi introduzido foi para evitar o famoso "callback hell", onde funções eram aninhadas vários níveis de profundidade. Isso acontece muito comumente quando o resultado de uma função requer mais consultas e validações.

Criaremos um fluxo de processo simples para exemplificar um "callback hell":

javascript
function suma(a, b, cb) {
  cb(a + b); // retorna a soma de dois números em um callback
}
function restar(valor, cantidad, cb) {
  cb(valor - cantidad); // subtrai uma certa quantidade de um valor
}
function esMayorACero(valor, cb) {
  if (valor > 0) {
    cb('Maior que zero');
  } else {
    cb('Menor que zero');
  }
}

const x = 10;
const y = 20;
// se houvesse ainda mais processos derivados, seria aninhado mais e mais
suma(x, y, function (resultado_de_suma) {
  // Resultado: 30
  restar(resultado_de_suma, 15, function (resultado_de_resta) {
    // Resultado: 15
    esMayorACero(resultado_de_resta, function (respuesta) {
      // Resultado: 'Maior que zero'
      console.log(respuesta); // Maior que zero
    });
  });
});

Este é um exemplo representativo, pois os callbacks são mais comumente usados para processos assíncronos, como solicitações de servidor.

Promises

Para reescrever o exemplo anterior, transformaremos as funções em promises:

javascript
function suma(a, b) {
  return new Promise(function (resolve, reject) {
    resolve(a + b);
  });
}
function restar(valor, cantidad) {
  return new Promise(function (resolve, reject) {
    resolve(valor - cantidad);
  });
}
function esMayorACero(valor) {
  return new Promise(function (resolve, reject) {
    if (valor > 0) {
      resolve('Maior que zero');
    } else {
      resolve('Menor que zero');
    }
  });
}

const x = 10;
const y = 20;

suma(x, y)
  .then(function (resultado_de_suma) {
    // Resultado: 30
    return restar(resultado_de_suma, 15);
  })
  .then(function (resultado_de_resta) {
    // Resultado: 15
    return esMayorACero(resultado_de_resta);
  })
  .then(function (respuesta) {
    // Resultado: 'Maior que zero'
    console.log(respuesta);
  });

Ao retornar uma promise, podemos encadear then() conforme elas são resolvidas.

Async/Await

Agora vamos reescrever o exemplo usando async/await. Como isso funciona com promises, usaremos as mesmas funções declaradas no código anterior.

Async/Await só funciona dentro de funções assíncronas, ou seja, funções com a sintaxe async function nome_da_funcao() {}.

javascript
const x = 10;
const y = 20;

// função assíncrona com "async"
async function mayorACero() {
  try {
    let resultado_de_suma = await suma(x, y); // Resultado: 30
    let resultado_de_resta = await restar(resultado_de_suma, 15); // Resultado: 15 
    let respuesta = await esMayorACero(resultado_de_resta); // Resultado: 'Maior que zero'
    console.log(respuesta);
  } catch (err) {
    // tratamento de erros
  }
}

mayorACero(); // Resultado: 'Maior que zero'

Se usássemos a sintaxe await fora de uma função async, resultaria em um erro.

Graças ao async/await, podemos lidar com funções assíncronas de uma maneira mais sequencial, proporcionando mais clareza ao nosso código.

É recomendado que, ao usar await, seja feito dentro de um try {} catch() {} para poder ter controle no catch() {} das promises que falham. Isso porque, se uma promise falhar dentro do try, o erro se propagará para o bloco catch.

Como async/await é relativamente novo, é recomendado usá-lo com cautela, pois não funciona em navegadores mais antigos como o IE11. Você pode ver seu suporte aqui.

Espero que este artigo tenha ajudado você a se familiarizar com alguns dos novos recursos do ECMAScript7, neste caso, async/await.