Skip to content

¿Qué es async await en JavaScript?

Introducción

Las funciones asíncronas utilizan la sintaxis async y await para esperar que una promesa sea resuelta. Para comprender mejor este artículo es recomendable conocer cómo funcionan las promesas. Pueden conocer sobre las mismas aquí.

Callback hell

Una de las razones por las que se introdujo async/await era para evitar el conocido "callback hell" en el que las funciones se anidaban varios niveles. Esto sucede muy comúnmente cuando el resultado de una función requiere de posteriores consultas y validaciones.

Crearemos un flujo de procesos sencillos para ejemplificar un "callback hell":

javascript
function suma(a, b, cb) {
  cb(a + b); // retorna la suma de dos numeros en un callback
}
function restar(valor, cantidad, cb) {
  cb(valor - cantidad); // resta una cantidad determinada a un valor
}
function esMayorACero(valor, cb) {
  if (valor > 0) {
    cb('Mayor a cero');
  } else {
    cb('Menor a cero');
  }
}

const x = 10;
const y = 20;
// si hubieran aún mas procesos derivados, se anidaría más y más
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: 'Mayor a cero'
      console.log(respuesta); // Mayor a cero
    });
  });
});

Este es un ejemplo representativo ya que los callbacks son usados más comúnmente para procesos asíncronos como peticiones a un servidor.

Promesas

Para reescribir el ejemplo anterior, transformaremos las funciones en promesas:

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('Mayor a cero');
    } else {
      resolve('Menor a cero');
    }
  });
}

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: 'Mayor a cero'
    console.log(respuesta);
  });

Al retornar una promesa, podemos encadenar los then() a medida que se resuelven.

Async/Await

Ahora reescribiremos el ejemplo usando async/await. Como esto funciona con promesas, usaremos las mismas funcionas declaradas en el código anterior.

Async/Await solo funcionan dentro de funciones asíncronas, es decir, las funciones con la sintaxis async function nombre_de_funcion () {}.

javascript
const x = 10;
const y = 20;

// función asíncrona con "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: 'Mayor a cero'
    console.log(respuesta);
  } catch (err) {
    // manejo de errores
  }
}

mayorACero(); // Resultado: 'Mayor a cero'

Si usaramos la sintaxis await fuera de una función con async resultaría en un error.

Gracias a async/await podemos manejar funciones asíncronas de manera más secuencial, brindándole más claridad a nuestro código.

Se recomienda que al usar await se haga dentro de un try {} catch() {} para poder tener control en el catch() {} de las promesas que fallen. Esto porque si una promesa falla dentro del try, el error se propagará al bloque catch.

Debido a que async/await es relativamente nuevo, se recomienda usarlo con precaución ya que no funciona en navegadores antiguos como IE11. Pueden ver el soporte de la misma aquí.

Espero este artículo les haya ayudado a familiarizarse con algunas de las novedades de ECMAScript7, en este caso, async/await.

¡Saludos!