👉 Ver todas las notas
Una de las principales desventajas de manejar asincrinismo en JavaScript, es que muchas veces resulta algo complejo razonar o seguir el flujo de las diferentes operaciones, principalmente porque estamos más acostumbrados a pensar de forma sincrónica.
Es por esto que en la versión ES2017 de JavaScript se incorporó una nueva forma de trabajar con código asincrónico, async/await
.
async/await
nos permite pausar la ejecución de funciones asincrónicas, para poder escribir código asincrónico que se lea como código sincrónico, resultando de esta forma, más legible y simple de razonar.
👉
async/await
no deja de ser sugar syntax (es decir, una forma más simple de escribir) sobre Promises
👉 El operador
async
transforma una función cualquiera en una que retorna una Promise. Entonces, al agregarasync
delante de cualquier función, esta pasa automáticamente a retornar una promesa al valor original que retornaba antes.
Por ejemplo, si tenemos
function sum(a, b) {
return a + b;
}
La función sum
retorna un número. Al agregar async
delante
async function sum(a, b) {
return a + b;
}
la función pasa a retornar una Promise
a este número.
👉 El operador
await
le indica a un valor o expresión cualquiera que tenga a continuación, que espere a que la Promise se resuelva antes de continuar (lo que haríamos con el.then()
) y extraer su valor ya resuelto, es decir, pausa la ejecución de la funciónasync
. Cuando se usa junto con la declaración de una variable o constante (var
,let
oconst
), asigna la respuesta de la promesa a la variable, en lugar de la promesa en si misma.
👉 await
sólo puede utilizarse dentro de una función async
Ejemplo usando fetch
async function getPost() {
const response = await fetch('https://jsonplaceholder.typicode.com/posts/5');
const post = await response.json();
console.log(post);
return post;
};
getPost();
👉 Algo importante de entender es que hablamos de pausar la ejecución de la función
async
pero no de bloquear. Async/Await no deja de ser otra forma de escribir Promises, por lo que se trata siempre de código asincrónico y no estamos bloqueando el Event Loop
Si miramos el ejemplo anterior, qué pasaría si por ejemplo el fetch
falla? No estamos manejando los errores de ninguna forma. Lo mismo sucede con .json()
.
Como fetch
retorna una promesa, podríamos simplemente agregar el catch()
async function getPost() {
const response = await fetch('https://jsonplaceholder.typicode.com/posts/5').catch(console.error);
const post = await response.json().catch(console.error);
console.log(post);
return post;
};
getPost();
Una mejor alternativa, para no estar mezclando sintaxis de Async/Await con Promises y simplificar el código, es utilizar el try/catch. Este suele ser el patrón utilizado para el manejo de errores (error handling) cuando usamos Async/Await.
La idea es simplemente, mover todo el código que podría fallar adentro del try
y si alguna promesa falla, manejar el error en el catch
async function getPost() {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts/5');
const post = await response.json();
console.log(post);
return post;
} catch (e) {
console.error(e.message);
}
};
getPost();
👉 Una función
async
retorna un valor envuelto en una Promise resuelta. Si queremos en cambio retornar una promesa rechazada, usamosthrow
dentro de la función
async function rejection() {
throw 'I'm rejecting this promise...';
}