Fetch() en JavaScript

Descubrí cómo usar fetch en JavaScript para conectar tu sitio con APIs y crear aplicaciones dinámicas sin recargar la página. En esta guía paso a paso vas a entender su funcionamiento, manejar datos en tiempo real y aplicarlo en proyectos reales de forma profesional.

que es fetch en javascript con ejemplos

1. ¿Qué es fetch() en JavaScript?

fetch() es un método global de la Fetch API que permite realizar peticiones HTTP de forma asíncrona en JavaScript.

Es la herramienta moderna que utilizan los desarrolladores web para comunicarse con servidores externos, permitiendo enviar o recibir datos (como archivos JSON o imágenes) sin necesidad de recargar la página completa.

1.1. ¿Para qué sirve exactamente?

En el desarrollo de aplicaciones modernas, fetch() cumple funciones críticas para la experiencia de usuario (UX) y el rendimiento:

Consumir APIs
Permite traer información desde una base de datos externa o servicios de terceros (como el clima, cotizaciones de monedas o listas de productos). Es fundamental para obtener datos dinámicos en aplicaciones web modernas.
Enviar datos al servidor
Se utiliza para procesar formularios, crear nuevos usuarios o enviar comentarios de forma silenciosa «por detrás». Permite interactuar con el backend sin recargar la página.
Actualizar contenido en tiempo real
Gracias a que trabaja con Promesas, permite que una parte de la web se actualice mientras el usuario sigue navegando, algo vital en redes sociales o paneles de control. Mejora la experiencia del usuario al evitar recargas completas.
Reemplazar al antiguo XMLHttpRequest
Ofrece una sintaxis mucho más limpia, potente y fácil de leer que las tecnologías legacy (antiguas). Facilita el desarrollo y mantenimiento del código moderno.

2. Sintaxis de uso

Para dominar la comunicación con servidores, es fundamental entender cómo se escribe correctamente una petición. La función fetch() tiene una estructura modular que nos permite controlar desde el destino del mensaje hasta la forma en que procesamos la respuesta.

2.1. La estructura completa de una petición fetch

Aunque muchas veces verás versiones simplificadas, la sintaxis completa de fetch se compone de la siguiente manera:

fetch(
  URL,                // 1. Destino (Obligatorio)
  { CONFIGURACIÓN }   // 2. Opciones de envío (Opcional)
)

.then(respuesta => {
  // 3. Procesamiento de la respuesta
})
.catch(error => {
  // 4. Gestión de errores de red
});Lenguaje del código: JavaScript (javascript)

Explicación detallada de la sintaxis:

  1. URL (String):
    • Es el único parámetro estrictamente obligatorio.
    • Es la dirección del recurso o la API a la que queremos consultar (ej: https://api.ejemplo.com/productos).
  2. CONFIGURACIÓN (Objeto):
    • Es un parámetro opcional.
    • Aquí definimos el método (POST, PUT, DELETE), los encabezados (Headers) y el cuerpo del mensaje (Body).
    • DATO CLAVE: Si no colocamos nada en este espacio, JavaScript asume por defecto que estamos haciendo una petición de tipo GET (solo lectura de datos).
  3. El bloque .then():
    • Es una Promesa. Se ejecuta automáticamente cuando el servidor responde.
    • Aquí es donde transformamos los datos «crudos» en algo que nuestra aplicación pueda entender, como un objeto JSON.
  4. El bloque .catch():
    • Es nuestro escudo de seguridad. Si el servidor no responde o el usuario pierde la conexión a internet, este bloque captura el fallo para evitar que la aplicación se detenga bruscamente.

¿En qué nos enfocaremos primero?

En este nivel del curso, vamos a profundizar exclusivamente en el manejo de la respuesta (el bloque .then y el .catch()).

¿Por qué lo hacemos así?
Aprender a recibir y procesar datos es el paso más importante y frecuente en el desarrollo frontend. Una vez que domines cómo leer la información que viene del servidor y cómo manejar los posibles errores de respuesta, pasaremos a la sección de configuración avanzada. Allí aprenderás a enviar tus propios datos, crear usuarios y autenticarte en APIs profesionales.

3. Ejemplo de uso

Para entender cómo funciona fetch() en un entorno real, imagina el siguiente escenario:
Estás construyendo una aplicación de contactos y necesitas traer una lista de nombres desde un servidor remoto para mostrarlos en tu sitio web.

En este caso, realizaremos una petición de tipo GET (la que viene por defecto) a una API de pruebas.

Fíjate cómo manejamos la llegada de los datos y los posibles errores:

// 1. Definimos la URL de la API (en este caso, una lista de usuarios)
const urlUsuarios = 'https://jsonplaceholder.typicode.com/users';

// 2. Ejecutamos la función fetch
fetch(urlUsuarios)
  .then(respuesta => {
    // 3. Verificamos si la respuesta del servidor es correcta
    if (!respuesta.ok) {
      throw new Error(`Error en la petición: ${respuesta.status}`);
    }
    // 4. Transformamos la respuesta en formato JSON
    return respuesta.json();
  })
  .then(usuarios => {
    // 5. ¡Éxito! Ahora recorremos el array de usuarios y los mostramos en consola
    console.log("Lista de usuarios recibida:");
    usuarios.forEach(usuario => {
      console.log(`- Nombre: ${usuario.name} | Email: ${usuario.email}`);
    });
  })
  .catch(error => {
    // 6. Si algo falla (ej. no hay internet), el error se captura aquí
    console.error("Hubo un problema con la operación fetch:", error.message);
  });Lenguaje del código: JavaScript (javascript)

Explicación paso a paso del código:

  1. Llamada Inicial:
    • Al ejecutar fetch(urlUsuarios), le pedimos al navegador que vaya a esa dirección y traiga la información. Como no agregamos el objeto de configuración, JavaScript entiende automáticamente que es una petición de lectura (GET).
  2. Validación de Respuesta (respuesta.ok):
    • Este es un paso profesional. Antes de intentar leer los datos, comprobamos si el servidor respondió bien. Si la URL estuviera mal escrita (error 404), este bloque lanzaría un error.
  3. Conversión a JSON:
    • Los datos viajan por internet como un «paquete cerrado» (stream). El método .json() es el encargado de «abrir el paquete» y convertirlo en un objeto o array de JavaScript que podamos usar.
  4. Uso de los Datos:
    • En el segundo .then(), ya tenemos acceso a la información real. En este ejemplo, usamos un forEach para imprimir los nombres y correos de cada usuario en la consola.
  5. Red de Seguridad (.catch):
    • Si el servidor está caído o el usuario pierde la conexión mientras se descarga la lista, el código no se «rompe». En su lugar, nos muestra un mensaje amigable explicando qué falló.

4. El flujo de ejecución de una Petición

Primero te dejo un resumen de este flujo y luego iremos profundizando:

  1. Llamada a fetch(url):
    • Se inicia una petición HTTP de forma asíncrona hacia el servidor.
  2. Retorno de una Promesa (estado pending):
    • fetch() devuelve inmediatamente una Promesa mientras espera la respuesta.
  3. Resolución de la Promesa con un objeto Response:
    • Cuando la petición se completa, la Promesa se resuelve y entrega un objeto Response (aunque el estado HTTP sea error).
  4. Inspección de la respuesta (propiedades de Response):
    • Se pueden revisar propiedades como status, ok, headers para validar la respuesta antes de procesarla.
  5. Procesamiento del cuerpo de la respuesta:
    • Se utilizan métodos como .json() o .text() para leer los datos (esto devuelve otra Promesa).
  6. Conversión de los datos (nueva Promesa):
    • El contenido se transforma a un formato utilizable (por ejemplo, objeto JavaScript desde JSON).
  7. Obtención y uso de los datos finales:
    • Una vez resuelta la conversión, ya se pueden usar los datos (por ejemplo, renderizar en el DOM).
  8. Manejo de errores:
    • Cualquier error de red o ejecución se captura con .catch() o try/catch si se usa async/await.
Flujo de funcionamiento de Fetch API

4.1. Funcionamiento de fetch()

Ahora, vamos a profundizar el procesos anterior, dividiéndolo en 5 fases:

// --- FASE 1: EL DISPARO (Petición enviada) ---
// El navegador inicia el viaje. La promesa está en estado "Pending".
fetch('https://jsonplaceholder.typicode.com/posts/1') 

  // --- FASE 2: EL CONTACTO (Respuesta inicial) ---
  // El servidor respondió las cabeceras. Recibimos el objeto 'response'.
  .then(response => {
    
    // --- FASE 3: LA INSPECCIÓN (Propiedades de Response) ---
    // Aquí revisamos los metadatos antes de descargar el contenido real.
    console.log("Estado HTTP:", response.status); // Ejemplo: 200
    console.log("¿Fue exitoso?:", response.ok);   // Ejemplo: true

    if (!response.ok) {
      // Si la inspección falla (ej. 404), forzamos el camino al error.
      throw new Error("El recurso no existe o el servidor falló.");
    }

    // --- FASE 4: LA EXTRACCIÓN (Variante de desempaquetado) ---
    // Elegimos .json() porque esperamos datos estructurados. 
    // Esto genera una nueva promesa interna.
    return response.json(); 
  })

  // --- FASE 5 (Variante A): EL ÉXITO (Datos listos) ---
  // Los datos ya fueron convertidos y están disponibles para tu lógica.
  .then(data => {
    console.log("--- Fase de Éxito ---");
    console.log("Contenido del post:", data.title);
  })

  // --- FASE 5 (Variante B): EL ERROR (Fallo de red o validación) ---
  // Solo se ejecuta si no hay internet o si lanzamos el 'throw' en la Fase 3.
  .catch(error => {
    console.log("--- Fase de Error ---");
    console.error("Motivo del fallo:", error.message);
  });Lenguaje del código: JavaScript (javascript)

EXPLICACIÓN:

Imaginalo como un túnel donde la información va cambiando de estado.

FASE 1: El Disparo (La Promesa Pendiente)

Cuando ejecutas fetch(URL), el navegador genera inmediatamente una Promesa.

  • Estado: Pending (Pendiente).
  • Qué sucede: El navegador prepara el paquete HTTP y lo envía por el cable hacia el servidor. Tu código sigue ejecutándose (asincronía), no se queda esperando ahí.

FASE 2: El Contacto (Llegada de la Respuesta)

Esta es la parte que más confunde: Fetch se resuelve en cuanto recibe las cabeceras (headers) del servidor, no cuando termina de descargar los datos.

  • Estado: Fulfilled (Resuelta).
  • Lo que recibes: Un objeto llamado Response.
  • NOTA! Para fetch, si el servidor respondió (aunque sea un Error 404 de «No encontrado»), la comunicación fue un éxito. La promesa no se rompe por un error de lógica del servidor.

FASE 3: La Inspección (Propiedades de Response)

Una vez que tienes el objeto Response en tus manos (en el primer .then), tienes varias «palancas» o propiedades para decidir qué hacer:

  1. response.ok (Booleano):
    • Es tu mejor amigo. Devuelve true si el código de estado está entre 200 y 299. Si es false, algo salió mal (ej. 404 o 500).
  2. response.status (Número):
    • Te da el código exacto (200, 403, 404, 500). Útil si quieres dar mensajes específicos según el error.
  3. response.headers:
    • Es un mapa con información extra (ej. qué tipo de archivo te enviaron).

FASE 4: La Extracción (Variantes del Cuerpo)

El cuerpo de la respuesta (el contenido real) llega como un «flujo de datos» (stream). No puedes leerlo directamente; tienes que elegir cómo quieres desempaquetarlo. Aquí es donde eliges una variante según lo que esperas recibir:

Método de extracción ¿Cuándo usarlo?
.json() Cuando esperas datos estructurados (objetos o arrays). Es el más común.
.text() Cuando esperas texto plano o código HTML.
.blob() Cuando estás descargando archivos binarios (imágenes, PDFs, audios).
.formData() Cuando el servidor te responde con datos de formulario.

Nota: Estos métodos también devuelven una promesa, porque el navegador necesita tiempo para terminar de descargar y convertir los datos.

FASE 5: El Final del Camino (Éxito o Fracaso)

Aquí es donde el flujo se bifurca definitivamente:

  1. VARIANTE del Éxito (.then final):
    • Los datos ya están convertidos (ej. a un objeto JS) y listos para ser usados en tu interfaz.
  2. VARIANTE del Error (.catch):
    • La promesa solo «salta» aquí si hubo un error de red real.
      • Ejemplos: El usuario no tiene internet, el DNS falló, o el servidor no existe físicamente.
      • Recordatorio: Un error 404 no cae aquí automáticamente a menos que tú lo provoques lanzando un throw Error.

5. La petición HTTP con fetch()

5.1. ¿Para qué sirve realmente esta fase?

El objetivo de la Fase 1 (la petición HTTP) es establecer una comunicación no bloqueante. Sirve para:

  1. Solicitar recursos externos:
    • Pedir datos a una base de datos sin congelar la pantalla.
  2. Interactuar con servicios de terceros:
    • Conectarse a APIs de mapas, clima, pagos o redes sociales.
  3. Optimizar la carga:
    • Cargar solo los datos necesarios en el momento justo, mejorando la velocidad percibida del sitio.

5.2. ¿Qué tipos de peticiones podemos realizar?

Aunque en los ejemplos básicos siempre usamos fetch(URL) para leer datos, en esta fase podemos configurar el «disparo» para diferentes acciones mediante los Métodos HTTP. Estos son los más importantes:

Método Función Analogía
GET Leer o solicitar datos del servidor (es el que viene por defecto). Consultar el precio de un producto.
POST Crear o enviar nueva información al servidor. Registrar un nuevo usuario en un formulario.
PUT Actualizar o reemplazar un recurso existente por completo. Cambiar toda la información de un perfil.
PATCH Modificar solo una parte pequeña de un recurso. Cambiar solo la contraseña de un usuario.
DELETE Eliminar un recurso del servidor. Borrar un comentario o una foto.

6. Primer .then(): El objeto response

6.1. El proceso: ¿Cómo llegamos hasta aquí?

Para que el objeto Response aparezca en tu código, primero debieron ocurrir estos pasos:

  1. El Disparo: Ejecutaste fetch(URL).
  2. El Viaje: El navegador envió un paquete HTTP al servidor.
  3. El Contacto: El servidor recibió la petición, la procesó y envió de vuelta un mensaje.
  4. El Nacimiento:
    • En cuanto el navegador recibe los Headers (cabeceras) del servidor, genera automáticamente el objeto Response y resuelve la primera fase de la Promesa.

6.2. ¿Qué es exactamente el objeto Response?

Es una interfaz de la Fetch API que representa la respuesta completa a una petición.

Imagínalo como el remito o etiqueta de un paquete de correo: antes de abrir la caja para ver qué hay dentro, lees la etiqueta para saber quién lo envía, cuánto pesa y si el envío fue exitoso.

¿Para qué sirve?
Sirve para inspeccionar los metadatos de la comunicación antes de gastar recursos descargando o procesando el contenido real.

6.3. Propiedades clave y sus funciones

Dentro del primer .then(response => { ... }), tienes acceso a estas propiedades fundamentales:

A. response.ok (La más importante)

  • QUÉ ES: Un valor booleano (true o false).
  • PARA QUÉ SIRVE: Es un atajo para saber si la petición tuvo éxito. Devuelve true si el código de estado está entre 200 y 299. Es la propiedad que usamos para decidir si seguimos adelante o lanzamos un error.

B. response.status

  • QUÉ ES: Un número entero (código de estado HTTP).
  • PARA QUÉ SIRVE: Indica exactamente qué pasó en el servidor.
    • 200: Todo OK.
    • 404: No encontrado.
    • 500: Error interno del servidor.
    • 403: Prohibido (falta de permisos).

C. response.statusText

  • QUÉ ES: Un mensaje de texto corto que acompaña al código.
  • PARA QUÉ SIRVE: Da una descripción humana al código (ej: «OK» para 200, o «Not Found» para 404). Útil para mostrar mensajes de error rápidos.

D. response.headers

  • QUÉ ES: Un objeto de tipo Headers.
  • PARA QUÉ SIRVE: Contiene información técnica extra sobre la respuesta, como el tipo de contenido (Content-Type: application/json) o la fecha del servidor.

E. response.url

  • QUÉ ES: Un string con la URL final.
  • PARA QUÉ SIRVE: Útil para saber si hubo redirecciones (si pediste la URL «A» pero el servidor te mandó a la «B»).

F. response.type

  • QUÉ ES: Indica el tipo de respuesta (ej: basic, cors, error).
  • PARA QUÉ SIRVE: Ayuda a saber si la petición fue a tu propio dominio o a uno externo con restricciones de seguridad.

6.4. Ejemplo usando el objeto response

Imagina que estás programando el acceso a un panel de administración. Tienes tres situaciones posibles:

  1. Éxito: El usuario entró correctamente (Status 200).
  2. Error de Cliente: El usuario no tiene permiso o se equivocó (Status 403 o 404).
  3. Error de Servidor: La base de datos del servidor se cayó (Status 500).

CÓDIGO: Este código utiliza las propiedades más importantes: ok, status y statusText.

// Simulamos una petición a una URL de un perfil de usuario
const urlPerfil = 'https://jsonplaceholder.typicode.com/users/1';

fetch(urlPerfil)
  .then(response => {
    // 1. Usamos .status para ver el código numérico
    console.log("Código de estado:", response.status); 

    // 2. Usamos .statusText para ver el mensaje del servidor
    console.log("Mensaje del servidor:", response.statusText);

    // 3. Usamos .ok como filtro principal de seguridad
    if (response.ok) {
      console.log("✅ ¡Acceso concedido! Preparando datos...");
      return response.json();
    } else {
      // Si .ok es false, evaluamos por qué falló
      if (response.status === 404) {
        console.error("❌ Error: El usuario no existe.");
      } else if (response.status === 500) {
        console.error("❌ Error: El servidor está en mantenimiento.");
      }
      throw new Error("Petición no exitosa");
    }
  })
  .then(data => {
    console.log("Nombre del usuario:", data.name);
  })
  .catch(error => {
    console.log("Aviso:", error.message);
  });
Lenguaje del código: JavaScript (javascript)

¿Dónde veo los resultados?

Para ver estas propiedades en acción, debes abrir las Herramientas de Desarrollador de tu navegador (Chrome, Firefox o Edge):

  1. La Consola (Console): Ahí es donde verás los console.log que escribimos. Verás algo como:
    • Código de estado: 200
    • Mensaje del servidor: OK
    • ✅ ¡Acceso concedido! Preparando datos…
  2. Pestaña de Red (Network): Si haces clic en la petición que dice «1», verás una columna llamada Status. Ahí el navegador te muestra visualmente lo mismo que extrajimos con response.status.

NOTA!!!! Si te animas y deseas ver el resultado de este ejemplo y de todos los que iremos proporcionando directamente desde tu PC, te invito a seguir estos pasos.

  1. Primero, revisa el punto 5 del siguiente artículo sobre como usar e instalar VSCode (este es el editor de código mas usado), donde encontrarás los pasos para crear la estructura necesaria para visualizar una página desde tu navegador predeterminado.
  2. Si entendiste correctamente este paso anterior, sabrás donde colocar el código script que te acabamos de proporcionar (arriba). Ahora, puedes visualizar el resultado, para ello puedes hacer lo siguiente:
    • Una vez abierta y visualizada la página, abre la consola del navegador presionando la tecla F12.
    • Ahora, dirígete a la pestaña que dice Console, y desde aquí podrás ver el resultado del script que hayamos introducido anteriormente.
  3. No te preocupes, estos pasos son más simples de lo que parecen!!!! Entonces… cada vez que dejemos un código de ejemplo como éste, puedes seguir estos pasos y ver los resultados por ti mismo. ¡Ojalá te animes!!!!

Link para descargar el editor de código Visual Studi Code!!

Usos de las propiedades del objeto:

  • response.ok: Úsalo siempre como el primer «if» para saber si sigues adelante.
  • response.status: Úsalo cuando necesites ser específico (ej: mostrar un mensaje distinto si es un error 404 vs un 500).
  • response.statusText: Úsalo para depuración rápida o logs internos, ya que te da el nombre del error en inglés (ej: «Not Found»).

CONCLUSIÓN: El objeto Response es el guardia de seguridad de tu petición: antes de dejar pasar los datos a tu aplicación, él te informa si la conexión es segura, si el servidor encontró lo que buscabas y qué tipo de información te está entregando.

7. Segundo .then(): La extracción

7.1. El Proceso: ¿Cómo llegamos hasta aquí?

Para situar al lector, recordemos el camino recorrido:

  1. Petición: Enviamos el fetch.
  2. Contacto: El servidor respondió y recibimos el objeto Response.
  3. Inspección: Revisamos response.ok y vimos que todo está en orden (Status 200).
  4. Llegada al Stream:
    • El servidor empieza a enviarnos los datos, pero no llegan como un archivo completo, sino como un «chorro» de bits continuo llamado ReadableStream.

7.2. ¿Por qué es importante este proceso? (El concepto de Stream)

Imagina que estás descargando una película de 2GB. Si JavaScript intentara meter esos 2GB de golpe en una variable, tu navegador se colgaría.

Por eso, los datos llegan como un Stream (flujo). La Fase de Extracción es el proceso de esperar a que todos esos trozos terminen de llegar y se «ensamblen» en un formato que JavaScript pueda entender (como un objeto, un texto o una imagen).

7.3. Variantes de extracción: Elegir herramienta

Dependiendo de qué haya enviado el servidor, debes elegir el método correcto para «desempaquetar». Estos métodos son asíncronos (devuelven una promesa) porque el navegador necesita tiempo para terminar la descarga y la conversión.

A. .json() (El Estándar de la Industria)

  • Uso real: Cuando pides una lista de productos, datos de un usuario o el clima.
  • Qué hace: Convierte el texto plano que viene del servidor en un Objeto o Array de JavaScript real.
  • Ejemplo: return response.json();

B. .text() (Para contenido simple)

  • Uso real: Cuando quieres leer un archivo .txt, un fragmento de código HTML para insertar en tu web, o un archivo CSV.
  • Qué hace: Entrega el contenido tal cual viene, como una cadena de texto (string).
  • Ejemplo: return response.text();

C. .blob() (Para archivos binarios)

  • Uso real: Cuando descargas una imagen de perfil, un PDF o un audio.
  • Qué hace: Crea un «Binary Large Object». Es la forma de manejar datos pesados que no son texto.
  • Ejemplo: Para mostrar una imagen descargada dinámicamente.

D. .formData() (Para formularios)

  • Uso real: Menos común en el frontend, pero útil si el servidor responde con un formato de formulario estructurado.

ACLARACIÓN!!!!! El cuerpo de una respuesta fetch solo se puede leer una vez.

Si intentas hacer esto, tu código lanzará un error:

.then(response => {
  response.json(); // 👈 Primera lectura
  response.text(); // ❌ ERROR: "body stream is locked"
})
Lenguaje del código: JavaScript (javascript)

¿Por qué? Porque una vez que el flujo de datos se «consume» y se transforma, el canal se cierra para ahorrar memoria. Si necesitas los datos en dos formatos, primero obtén el JSON y luego conviértelo tú mismo, o usa técnicas avanzadas como response.clone().

7.4. Ejemplo de extracción con json()

Imagina que estás programando una tienda de tecnología. El servidor te envía la información de un producto, pero te la envía como un «chorro de texto» (stream). Tú necesitas «desempaquetarlo» para extraer el nombre y el precio y mostrarlos en tu página.

CÓDIGO:

Este es el código estándar. Observa cómo el primer .then se encarga de la Fase 4 (Extracción) para que el segundo .then pueda usar los datos.

// URL de un producto de prueba (usamos una API real y gratuita)
const urlProducto = 'https://fakestoreapi.com/products/1';

fetch(urlProducto)
  .then(response => {
    // FASE 3: Verificamos si la caja llegó bien
    if (!response.ok) throw new Error("Error al conectar");

    // FASE 4: DESEMPAQUETADO (Extracción JSON)
    // Aquí transformamos el "chorro de datos" en un Objeto JS
    return response.json(); 
  })
  .then(producto => {
    // FASE 5: USO DE DATOS
    // Ahora 'producto' es un objeto real con propiedades
    console.log(`📦 Producto: ${producto.title}`);
    console.log(`💰 Precio: $${producto.price}`);
  })
  .catch(error => console.error("Fallo:", error));Lenguaje del código: JavaScript (javascript)

¿Cuál es el resultado?

Si ejecutas este código en la Consola de tu navegador, verás lo siguiente:

📦 Producto: FJALLRAVEN – FOLDSACK NO. 1 BACKPACK, FITS 15 LAPTOPS
💰 Precio: $109.95

¿Qué pasó realmente aquí?

  • El servidor envió: {"id":1, "title":"...", "price":109.95} (como texto plano).
  • .json() leyó ese texto y creó un objeto de JavaScript.
  • Gracias a eso, pudiste escribir producto.title para obtener el nombre. Sin la extracción, ¡JavaScript no sabría qué hay dentro de la respuesta!

8. El error (.catch) – Tu red de seguridad

8.1. ¿Para qué sirve el bloque .catch()?

El método .catch() sirve para capturar cualquier Promesa Rechazada (Rejected) que ocurra en cualquier punto de la cadena anterior. Su función es evitar que un fallo detenga la ejecución de todo tu script y permitirte dar una respuesta elegante al usuario (como mostrar un mensaje de «Inténtalo más tarde»).

8.2. ¿En qué casos llegamos aquí? (Cuando SÍ se activa)

El .catch() se dispara principalmente por fallos físicos o de conexión, es decir, cuando la comunicación no pudo completarse. Los escenarios reales son:

  1. Falta de Internet:
    • El usuario pierde la conexión wifi o datos móviles durante la petición.
  2. URL inexistente (Dominio):
    • Escribiste mal el dominio (ej: https://api.gogle.com en lugar de google.com). El navegador no encuentra a quién preguntarle.
  3. CORS (Seguridad):
    • El servidor bloquea la petición por políticas de seguridad entre diferentes dominios.
  4. Errores manuales (Throw):
    • Si tú, dentro de un .then(), lanzas un error manualmente con throw new Error(), el flujo saltará inmediatamente al .catch().

8.3. ¿Cuándo NO se activa el .catch()?

El .catch() NO se activa si el servidor responde con un Error 404 o 500.

  • Por qué: Para JavaScript, si el servidor respondió algo (aunque sea un mensaje de «Página no encontrada»), la comunicación fue exitosa. Hubo «ida y vuelta».
  • Consecuencia: Un error 404 entrará al primer .then(), no al .catch(). Por eso es obligatorio usar if (!response.ok) para «empujar» manualmente ese error hacia el catch.

8.4. Ejemplo que aplica para .catch()

Imagina que un usuario está enviando un formulario de contacto y justo en ese momento entra a un túnel y pierde la señal.

fetch('https://api.apinem.com/contacto')
  .then(res => {
    if (!res.ok) throw new Error("Error del servidor"); // Forzamos el paso al catch si hay 404/500
    return res.json();
  })
  .then(data => console.log("Enviado!"))
  .catch(error => {

    // Escenario: El usuario no tiene internet
    console.error("🚩 No pudimos enviar tu mensaje. Revisa tu conexión.");
    // Aquí podrías mostrar un aviso visual en la web

  });Lenguaje del código: JavaScript (javascript)

8.5. Situaciones que aplican para .catch o un .then

Situación ¿Dónde cae? Acción recomendada
Todo funciona (200 OK) .then() Usar los datos.
No se encuentra (404) .then() Validar con res.ok y lanzar error.
Sin Internet / DNS fallido .catch() Avisar al usuario que revise su conexión.
Error en el código del .then .catch() Útil para atrapar errores de programación propios.

9. Manipulación del DOM con Fetch() APIs

9.1. ¿Cómo se relaciona fetch con el DOM?

Imagina que fetch es el mensajero que trae la mercadería (los datos) desde un depósito lejano (el servidor), y el DOM es la estantería de tu local (tu página web).

La relación es de dependencia directa:

  • fetch obtiene los datos asíncronamente.
  • El DOM espera a que esos datos lleguen para «dibujarlos» en el navegador.

Sin esta integración, los datos de una API serían invisibles para el usuario. Gracias a ella, podemos crear Single Page Applications (SPA) donde el contenido cambia sin que la página se recargue por completo.

9.2. ¿Para qué sirve el renderizado dinámico?

El renderizado dinámico sirve para que tu web sea «viva». Sus usos reales más importantes son:

  • Listas de datos: Mostrar productos de una tienda, mensajes de un chat o noticias de última hora.
  • Buscadores en tiempo real: A medida que el usuario escribe, el DOM se actualiza con resultados de un fetch.
  • Dashboards: Gráficos y tablas que se actualizan solos cada cierto tiempo.

9.3. Técnicas de integración: ¿Cómo inyectar los datos?

Existen dos caminos principales para llevar los datos del fetch al HTML:

A. innerHTML

Consiste en escribir el HTML como si fuera un texto (string) e insertarlo en un contenedor.

  • Uso: Ideal para prototipos rápidos o estructuras simples.
  • Riesgo: Si los datos vienen de una fuente no confiable, puede haber problemas de seguridad (XSS).
// Ejemplo rápido dentro del .then()
.then(productos => {
  const contenedor = document.getElementById('lista');
  productos.forEach(p => {
    contenedor.innerHTML += `<li>${p.nombre} - $${p.precio}</li>`;
  });
});Lenguaje del código: JavaScript (javascript)

B. createElement

Es más seguro y eficiente. Creamos cada elemento como un objeto de JavaScript y lo «colgamos» en el DOM.

  • Uso: Recomendado para aplicaciones grandes y profesionales.
  • Ventaja: Tienes control total sobre cada elemento (puedes agregarle eventos de clic, clases de CSS, etc.).
// Ejemplo profesional dentro del .then()
.then(productos => {
  const listaUL = document.getElementById('lista');
  productos.forEach(p => {
    const li = document.createElement('li'); // Creamos el <li>
    li.textContent = `${p.nombre} - $${p.precio}`; // Agregamos texto seguro
    li.classList.add('item-producto'); // Agregamos una clase CSS
    listaUL.appendChild(li); // Lo metemos en el HTML
  });
});Lenguaje del código: JavaScript (javascript)

9.4. Flujo de trabajo (Step-by-Step)

Este es el orden que siempre deben seguir:

  1. Seleccionar el contenedor:
    • Identificar en el HTML dónde irá la información (ej: un div con id=»app»).
  2. Llamar al fetch:
    • Pedir los datos a la API.
  3. Limpiar el contenedor (Opcional):
    • Borrar el mensaje de «Cargando…» antes de poner los datos reales.
  4. Recorrer los datos:
    • Usar un bucle (forEach o map) para procesar cada elemento recibido.
  5. Renderizar:
    • Crear el HTML e inyectarlo.

9.5. Ejemplo, integrando datos traídos con fetch al DOM

Imagina que estás desarrollando la sección «Nuestro Equipo» para una empresa. En lugar de escribir el HTML de cada empleado a mano (lo cual sería eterno si son 100), decides usar fetch para traer los datos desde una base de datos y JavaScript para «dibujar» las tarjetas de cada persona automáticamente.

CÓDIGO:

Este código utiliza la técnica profesional de createElement para asegurar que el contenido sea seguro y fácil de manejar.

Primero, el HTML base:

<div id="contenedor-equipo">
    <p id="mensaje-carga">Cargando equipo de trabajo...</p>
</div>Lenguaje del código: HTML, XML (xml)

Ahora, el JavaScript que hace la magia:

const contenedor = document.getElementById('contenedor-equipo');
const mensaje = document.getElementById('mensaje-carga');

// 1. Iniciamos el fetch
fetch('https://jsonplaceholder.typicode.com/users')
  .then(res => {
    if (!res.ok) throw new Error("Error al obtener el equipo");
    return res.json();
  })
  .then(usuarios => {
    // 2. Limpiamos el mensaje de carga
    mensaje.remove();

    // 3. Recorremos el array de usuarios
    usuarios.forEach(usuario => {
      // FASE DE RENDERIZADO:
      // Creamos una "tarjeta" (div) para cada usuario
      const card = document.createElement('div');
      card.style.border = "1px solid #ccc";
      card.style.padding = "10px";
      card.style.margin = "10px";
      card.style.borderRadius = "8px";

      // Creamos el nombre (h3)
      const nombre = document.createElement('h3');
      nombre.textContent = usuario.name;

      // Creamos el email (p)
      const email = document.createElement('p');
      email.textContent = `📧 Email: ${usuario.email}`;

      // 4. Integramos todo: Metemos el h3 y el p dentro del div (card)
      card.appendChild(nombre);
      card.appendChild(email);

      // 5. Metemos la card final en nuestro contenedor del DOM
      contenedor.appendChild(card);
    });
  })
  .catch(err => {
    mensaje.textContent = "Hubo un error al cargar el equipo.";
    console.error(err);
  });Lenguaje del código: JavaScript (javascript)

🖥️ Resultado esperado

Al cargar la página, el usuario verá inicialmente el texto «Cargando equipo de trabajo…». Un segundo después, ese texto desaparecerá y en su lugar aparecerán 10 tarjetas blancas con bordes redondeados, cada una con el nombre de un empleado en negrita y su correo electrónico debajo.

Explicación del código:

  1. El Contenedor (getElementById):
    • Es el punto de anclaje. Sin esto, JavaScript no sabe dónde «pegar» la información.
  2. El Bucle (forEach):
    • Como la API nos devuelve una lista (array), usamos este método para repetir la creación de la tarjeta por cada persona que venga en los datos.
  3. createElement vs textContent:
    • Usamos createElement para generar las etiquetas <div>, <h3> y <p> desde cero. Usamos textContent para asignar los datos de forma segura, evitando que si un nombre trae código malicioso, este se ejecute (protección contra XSS).
  4. appendChild: Esta es la función clave de la integración. Es la que «pega» un elemento dentro de otro, construyendo la jerarquía del HTML dinámicamente.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *