DMarlon Studio

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.

JavaScript · async y await en DMarlon Studio: el código del ejemplo y su salida en la terminal

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 async siempre devuelve una promesa.
  • await pausa solo la función actual hasta que la promesa se resuelve.
  • Un rechazo dentro de await se captura con try/catch.
  • En CommonJS, el await va dentro de una función async como main().

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.