Hay una sintaxis especial que puedes usar en JavaScript y que te facilita el trabajo con promesas. Se llama "async / await" y es sorprendentemente fácil de entender y usar.
En este artículo, hablaré de:
- ¿Qué son las funciones asíncronas?
- Cómo funcionan las promesas en JavaScript
- Conceptos básicos de Async / Await
- Cómo usar async / await con manejo de errores
- Cómo una función asíncrona devuelve una promesa
- Cómo utilizar
promise.all()
Así que vamos allá
¿Qué son las funciones asíncronas?
El término asíncrono se refiere a una situación en la que dos o más eventos no ocurren al mismo tiempo. O en términos más sencillos, pueden suceder varias cosas relacionadas sin esperar a que se complete la acción anterior.
En JavaScript, las funciones asíncronas son muy importantes debido a la naturaleza de un solo subproceso de JavaScript. Con la ayuda de funciones asíncronas, el bucle de eventos de JavaScript puede encargarse de otras cosas cuando la función solicita algún otro recurso.
Usarías un código asíncrono, por ejemplo, en las API que obtienen un archivo de la red, cuando accedes a una base de datos y devuelves datos de ella, cuando accedes a una transmisión de video desde una cámara web, o si estás transmitiendo la pantalla a un headset de realidad virtual.
Cómo funcionan las promesas en JavaScript
El objeto Promise
en JavaScript representa una operación asíncrona (y su valor resultante) que eventualmente se completará (o fallará).
Una Promise
puede estar en uno de estos estados:
- pending (pendiente): estado inicial, ni cumplida ni rechazada.
- fulfilled (cumplida): significa que la operación se completó con éxito.
- rejected (rechazada): significa que la operación falló.

La función que se pasa a una nueva promesa se llama ejecutora. Sus argumentos (resolve
yreject
) se denominan callbacks y los proporciona JavaScript. Cuando el ejecutor obtiene el resultado, ya sea ahora o más tarde, debe llamar a una de estas callbacks.
Aquí va un ejemplo de una promesa:
const miPromesa = new Promise(function(resolve, reject) => {
setTimeout(() => {
resolve('foo');
}, 300);
});
Y aquí van ejemplos de una promesa cumplida frente a una promesa rechazada:
// promesa cumplida
let promesa = new Promise(function(resolve, reject) {
setTimeout(() => resolve(new Error("Hecho!")), 1000);
});
// resolve ejecuta la primera funcion en .then
promesa.then(
result => alert(result), // Muestra "hecho!" depues de 1 segundo
error => alert(error) // no se ejecuta
);
// promesa rechazada
let promesa = new Promise(function(resolve, reject) {
setTimeout(() => reject(new Error("Whoops!")), 1000);
});
// reject ejecuta la segunda funcion en .then
promesa.then(
result => alert(result), // No se ejecuta
error => alert(error) // Muestra "Error: Whoops!" despues de 1 segundo
);
Conceptos básicos de Async / Await en JavaScript
Tenemos dos partes cuando usamos async/await
en nuestro código.
En primer lugar, tenemos la palabra clave async
, que se pone delante de una declaración de función para convertirla en una función async.
Una función asíncrona es una función que sabe que es posible que se use la palabra clave await
dentro de ella para invocar código asíncrono.
La palabra clave async
se añade a las funciones para que devuelvan una promesa en lugar de un valor directamente.
const cargarDatos = async () => {
const url = "https://jsonplaceholder.typicode.com/todos/1";
const res = await fetch(url);
const datos = await res.json();
console.log(datos);
};
cargarDatos();
// output en la consola
{
completed: false,
id: 1,
title: "delectus aut autem",
userId: 1
}
Cómo usar Async/Await con manejo de errores
Podemos manejar errores usando un bloque try catch como este:
const cargarDatos = async () => {
try{
const url = "https://jsonplaceholder.typicode.com/todos/1";
const res = await fetch(url);
const datos = await res.json();
console.log(datos);
} catch(err) {
console.log(err)
}
};
cargarDatos();
El try-catch anterior solamente manejará errores al obtener los datos, como una sintaxis incorrecta, nombres de dominio incorrectos, errores de red, etc.
Cuando quieras manejar un mensaje de error del código de respuesta de la API, puedes usar res.ok
( res
es la variable en la que se almacena la respuesta). Te dará un Boolean con el valor verdadero si el código de respuesta está entre 200 y 209.
const cargarDatos = async () => {
try{
const url = "https://jsonplaceholder.typicode.com/todos/qwe1";
const res = await fetch(url);
if(res.ok){
const datos = await res.json();
console.log(datos);
} else {
console.log(res.status); // 404
}
} catch(err) {
console.log(err)
}
};
cargarDatos();
// OUTPUT
// 404
Cómo una función Async devuelve una promesa
Este es uno de los rasgos de las funciones asíncronas — se garantiza que sus valores de retorno se convertirán en promesas. Para manejar los datos devueltos por una función async
podemos usar una palabra clave then
para obtener los datos.
const cargarDatos = async () => {
try{
const url = "https://jsonplaceholder.typicode.com/todos/1";
const res = await fetch(url);
const datos = await res.json();
return datos
} catch(err) {
console.log(err)
}
};
const datos = cargarDatos().then(datos => console.log(datos));
? PRO TIP :
Si quieres usar un async-await
para manejar los datos devueltos puedes utilizar un IIFE, pero solo está disponible en Node 14.8 o superior.
// usa una IIFE asincrona
(async () => {
const datos = await cargarDatos();
console.log(datos);
})();
await
solo funciona dentro de funciones asíncronas en JavaScript normal. Pero puede usarlo por sí misma con módulos JavaScript.
Cómo usar Promise.all () en JavaScript
Promise.all()
es muy útil cuando queremos llamar a varias APIs.
Utilizando una función con await
de manera tradicional, tenemos que esperar a que se complete cada solicitud antes de pasar a la siguiente. Esto puede ser un problema cuando cada solicitud tarda en completarse. Esto puede hacer que la respuesta sea muy lenta.
Usando Promise.all()
, podemos llamar a cada una de estas API en paralelo. (Esto es una explicación muy básica – Para una explicación más detallada consulta este estupendo artículo) .
Ten cuidado cuando uses Promise.all()
, – si una de las solicitudes con await falla, todo el .all() falla.
const cargarDatos = async () => {
try{
const url1 = "https://jsonplaceholder.typicode.com/todos/1";
const url2 = "https://jsonplaceholder.typicode.com/todos/2";
const url3 = "https://jsonplaceholder.typicode.com/todos/3";
const resultados = await Promise.all([
fetch(url1),
fetch(url2),
fetch(url3)
]);
const promesasDeDatos = await resultados.map(result => result.json());
const datosFinales = Promise.all(promesasDeDatos);
return datosFinales
} catch(err) {
console.log(err)
}
};
const datos = cargarDatos().then(datos => console.log(datos));
// output en la consola
[{
completed: false,
id: 1,
title: "delectus aut autem",
userId: 1
}, {
completed: false,
id: 2,
title: "quis ut nam facilis et officia qui",
userId: 1
}, {
completed: false,
id: 3,
title: "fugiat veniam minus",
userId: 1
}]
Conclusión
En la mayoría de las situaciones, podemos usar async/await
con un bloque try catch
para manejar tanto los resultados como los errores.
Por el momento, await
no funcionará en el código al nivel superior. Esto quiere decir que si estamos fuera de una función asíncrona (async
), no podemos usar await
sintácticamente. En este caso, lo habitual es agregar .then/catch
para manejar el resultado final o el error.
A nivel superior en el código , await
está disponible en Node.js v14.8
o superior y solamente en módulos ES. Puedes ver más aquí: Top-level await is available in Node.js modules | Stefan Judis Web Development
Recursos que me han ayudado
- Promises (javascript.info)
- Introducing asynchronous JavaScript - Learn web development | MDN (mozilla.org)
- Promise - JavaScript | MDN (mozilla.org)
Antes de terminar...
? ¿Quieres escribir código y aprender conmigo? Puede encontrar el mismo contenido aquí en mi blog. Simplemente abre tu editor de código favorito y empieza.
Soy Milind. Soy un full-stack developer y blogger. En este sitio web exploramos estrategias y herramientas que nos ayudan a escribir un código mejor y más limpio.
Vamos a conectar. Puedes seguirme en Twitter (@milindsoorya) donde estoy muy activo.
Traducido del artículo de Milind Soorya - How to Use Async/Await to Write Better JavaScript Code