Lección 12 · 12 de 20
async y await · JavaScript
Escriba código asíncrono en JavaScript que se lee de arriba abajo con async y await, y trate sus errores con try/catch.

Una función marcada con `async` siempre devuelve una promesa, aunque dentro haga return de un valor normal: la primera línea de la salida lo confirma (Promise). Lo que devuelve se convierte en el valor de la promesa, y lo que lanza con throw, en su rechazo, como hace getUser cuando el usuario no existe.
`await` espera a que una promesa se resuelva y entrega su valor. En cartSummary, el código se lee de arriba abajo, como si fuera síncrono: primero el usuario, luego su carrito y después el total. Mientras espera, solo se pausa esa función; el resto del programa (otros temporizadores, eventos) sigue funcionando.
Los errores se tratan con el `try`/`catch` de siempre: si la promesa de un await se rechaza, el error salta al catch. Así, el usuario 3 produce Error: user 3 not found sin detener el programa, y Luis, cuyo carrito no existe, aparece con 0 items gracias a ?? [].
Como en CommonJS no se puede usar await fuera de una función, el programa va dentro de async function main(), que se llama al final. En el bucle for...of, cada await espera a que termine un resumen antes de empezar el siguiente. En los destinos Electron, React, Next.js y React Native de DMarlon Studio, este es el estilo que verá para leer datos de una API o de una base de datos.
Código · main.js
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));const users = { 1: { name: "Ana", cartId: 10 }, 2: { name: "Luis", cartId: 20 } };const carts = { 10: [{ item: "Book", price: 15 }, { item: "Lamp", price: 32 }] };async function getUser(id) { await delay(20); // pretend this is a database query if (!users[id]) throw new Error(`user ${id} not found`); return users[id];}async function getCart(cartId) { await delay(20); return carts[cartId] ?? [];}// await pauses this function (not the whole program) until the promise settles.async function cartSummary(userId) { try { const user = await getUser(userId); const cart = await getCart(user.cartId); const total = cart.reduce((sum, line) => sum + line.price, 0); return `${user.name}: ${cart.length} items, ${total} EUR`; } catch (err) { return `Error: ${err.message}`; // a rejected await lands in catch }}async function main() { const pending = cartSummary(1); console.log("An async function returns:", pending.constructor.name); console.log(await pending); for (const id of [2, 3]) console.log(await cartSummary(id)); console.log("Done");}main();Salida · node main.js
An async function returns: Promise Ana: 2 items, 47 EUR Luis: 0 items, 0 EUR Error: user 3 not found Done
Para recordar
- Una función
asyncsiempre devuelve una promesa. awaitpausa solo la función actual hasta que la promesa se resuelve.- Un rechazo dentro de
awaitse captura contry/catch. - En CommonJS, el
awaitva dentro de una funciónasynccomomain().
Ejercicio
Añada una función async getDiscount(user) que espere 10 ms y devuelva un 10 % para Ana y un 0 % para los demás, y úsela en cartSummary para mostrar el total con descuento.