En el desarrollo de JavaScript, manejar operaciones asincrónicas es fundamental. Existen dos enfoques principales para hacerlo: Promesas con Then y Async/Await. A continuación, exploraremos las diferencias entre estos dos métodos y proporcionaremos ejemplos de cada uno.

Promesas con Then

Una Promesa es un objeto que representa la eventual finalización (o falla) de una operación asincrónica y su valor resultante. Las Promesas disponen de métodos como .then() y .catch() para manejar los resultados y errores respectivamente.

const getData = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('Datos obtenidos después de 2 segundos');
    }, 2000);
  });
};

getData()
  .then(data => {
    console.log(data);
  })
  .catch(error => {
    console.error(error);
  });

Async/Await

Async/Await es una sintaxis más reciente introducida en ES2017 que permite escribir código asincrónico de manera más sencilla y legible. Al utilizar la palabra clave async antes de una función, esta devuelve una Promesa de forma implícita, y await se usa dentro de funciones async para esperar a que una promesa se resuelva.

const getDataAsync = async () => {
  try {
    const data = await getData();
    console.log(data);
  } catch (error) {
    console.error(error);
  }
};

getDataAsync();

Comparación

CaracterísticaPromesasAsync/Await
Sintaxis.then() y .catch()await
Manejo de Errores.catch()try/catch
LegibilidadMás complejo con muchas promesas anidadasMás legible y manejable, similar a código sincrónico

Cuándo Usar Async/Await y Cuándo No

El uso de async/await o Promesas con then depende del contexto y la naturaleza de la operación asincrónica. A continuación, se presentan algunas pautas para decidir cuándo usar cada uno.

  • Si una función depende del resultado de otra función asincrónica, usa async/await para esperar la respuesta antes de continuar con la ejecución.
  • Si las operaciones pueden ejecutarse en paralelo y no dependen unas de otras, no uses await, permitiendo así que se ejecuten en paralelo.
  • Si solo deseas realizar una acción adicional una vez que una operación asincrónica se complete y no necesitas pausar la ejecución del programa, considera usar Promesas con then.

Ejemplos Prácticos

A continuación, se presentan ejemplos que ilustran los diferentes escenarios.

1. Usar async/await cuando una función depende del resultado de otra función asincrónica:

const fetchData = async () => {
  const data = await getData();// La siguiente línea espera el resultado de getData()
  console.log(data);
};

fetchData();

2. No usar await para operaciones que pueden ejecutarse en paralelo:

const fetchMultipleData = () => {
  const dataPromise1 = getData(); // Se inicia la operación asincrónica
  const dataPromise2 = getOtherData(); // Otra operación asincrónica

  console.log('Haciendo otras tareas mientras se obtienen los datos');

  dataPromise1.then(data1 => console.log(data1));
  dataPromise2.then(data2 => console.log(data2));
};

fetchMultipleData();

3. Usar then para realizar una acción adicional una vez que una operación asincrónica se complete:

getData()
  .then(data => {
    console.log('Datos obtenidos:', data);
    return processData(data); // Dispara otro evento
  })
  .then(result => console.log('Resultado procesado:', result))
  .catch(error => console.error('Error:', error));

Convertir una Función en una Promesa

A veces es necesario convertir una función que no es promesa en una para poder manejarla asincrónicamente. Esto se puede hacer envolviendo dicha función dentro de un nuevo contexto de Promesa.

const traditionalFunction = (callback) => {
  setTimeout(() => {
    callback(null, 'Datos obtenidos');
  }, 2000);
};

const convertToPromise = () => {
  return new Promise((resolve, reject) => {
    traditionalFunction((error, data) => {
      if (error) reject(error);
      else resolve(data);
    });
  });
};

convertToPromise()
  .then(data => console.log(data))
  .catch(error => console.error(error));

Tener en cuenta

Cuando se añade la palabra clave async a una función en JavaScript, dicha función se convierte automáticamente en una Promesa. Esto significa que su valor de retorno será una Promesa de forma implícita y, por lo tanto, debe ser gestionada como tal.

Una función marcada como async puede ser tratada utilizando then para manejar la Promesa generada:

async function exampleFunction() {
  return 'Valor de retorno';
}

exampleFunction().then(value => {
  console.log(value); // 'Valor de retorno'
});

No es recomendable usar async para convertir una función en promesa ya que no es su naturaleza, siempre usa return New Promise para retornar una promesa, como lo vimos en los ejemplos anteriores.

Alternativamente, dentro de una función async, se puede usar await para esperar a que la Promesa se resuelva:

async function anotherExample() {
  const result = await exampleFunction();
  console.log(result); // 'Valor de retorno'
}

anotherExample();

Es esencial tratar funciones async como Promesas, utilizando then o await según sea necesario, para gestionar adecuadamente el código asincrónico y asegurar un manejo correcto de los resultados.

Conclusión

Manejar operaciones asincrónicas es crucial en el desarrollo de JavaScript. Con Seguir usando Promesas con Then o migrar a la sintaxis más moderna de Async/Await depende del contexto y la preferencia personal, pero conocer ambos enfoques permite escribir código más robusto y legible.