Crear productos con fetch y POST

Resumen

Crear un producto con el verbo POST de HTTP es uno de los pasos más comunes al integrar un API REST con JavaScript. Aquí aprenderás a implementar el método createProduct dentro de un repositorio, manejar headers, body y errores comunes que aparecen al hacer la petición con fetch.

Qué define una petición POST en un API REST

El verbo HTTP determina la acción que se ejecuta sobre un recurso, aunque la URL sea la misma que usas para listar productos.

En la especificación del API que se trabaja en la clase, el endpoint de productos acepta dos verbos sobre la misma URL: GET para traer la lista y POST para crear uno nuevo. Lo que cambia no es la dirección, sino la intención. Y esa intención se expresa en el atributo method dentro de la configuración de fetch [01:25].

El body que espera este endpoint tiene una forma muy específica:

  • title: string que funciona como identificador único.
  • price: número.
  • description: string.
  • categoryId: número que referencia la categoría.
  • images: lista de strings con las URLs.

¿Qué hace el verbo POST en un API? Indica al servidor que quieres crear un nuevo recurso. Aunque uses la misma URL del GET, el servidor interpreta la acción según el method que envías en la petición.

Cómo implementar createProduct en el repositorio

El método vive dentro del repositorio de productos y encapsula la interacción con el API. Así, el resto de la aplicación solo invoca createProduct(product) sin preocuparse por los detalles de la petición.

La estructura base reutiliza la misma URL del listado, pero ahora declarada como const porque no hay query params que modificar. El cambio importante está en el segundo argumento de fetch, que recibe un objeto de configuración con method, headers y body [02:30].

Por qué necesitas JSON.stringify y los headers correctos

Al ejecutar la primera versión del método aparece un error revelador: el payload que se envía es un objeto de JavaScript en crudo, no una cadena JSON. El servidor no puede interpretarlo.

La solución tiene dos partes:

  1. Convertir el objeto con JSON.stringify(product) antes de asignarlo al body.
  2. Agregar el header Content-Type: application/json para indicarle al servidor el formato que estás enviando.

El header Accept: application/json complementa la conversación porque le dice al servidor en qué formato esperas la respuesta. Sin ambos headers la petición queda incompleta [05:40].

javascript async createProduct(product) { const url = ${this.baseUrl}/products; const response = await fetch(url, { method: 'POST', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify(product) });

if (!response.ok) { throw new Error(No se pudo crear el producto. statusCode: ${response.status}); }

const jsonResponse = await response.json(); return jsonResponse; }

Cómo manejar errores 400 y 500 al crear un producto

Una petición POST exitosa responde con status code 201, lo que activa el atributo response.ok en true. Cualquier valor distinto entra en la rama del throw new Error, donde un template tag expone el código real para depurar más rápido.

Durante la prueba aparecen dos errores típicos:

  • Error 500: ocurre cuando el body llega como objeto JS sin serializar.
  • Error 400: ocurre cuando intentas crear un producto cuyo title ya existe, porque ese campo se usa para generar el slug único.

¿Por qué falla mi POST con error 400? Casi siempre es un problema del body. Revisa el preview en la pestaña Network del navegador: el API devuelve ahí el detalle del error, como un título duplicado o un campo faltante.

Cómo integrar createProduct con el formulario de la vista

La vista create.html ya tiene un formulario y una función handleSubmit que captura los datos. Lo único que falta es conectar esa función con el repositorio.

El primer paso es importar el script de repositorios dentro del HTML para que window.productRepository quede disponible. Después, dentro de handleSubmit, se obtiene la instancia y se ajusta el productData para que cumpla la forma del API, especialmente el campo images, que debe ser una lista de strings aunque venga de un único input [09:15].

Cuándo usar then en lugar de async await

La función handleSubmit no está marcada como async, y convertirla obligaría a propagar async en cadena por todas las funciones que la invocan. Para evitar ese efecto dominó, se usa .then() directamente sobre la promesa que retorna createProduct.

javascript const repository = window.productRepository;

repository.createProduct(productData) .then((jsonResponse) => { console.log(jsonResponse); });

Esto aprovecha que fetch ya devuelve una promesa y mantiene el flujo del formulario sincrónico desde la perspectiva del DOM.

¿Qué retorna el API cuando se crea un producto? El mismo objeto que enviaste, pero con un id asignado por el servidor. Ese id confirma que el recurso quedó persistido en la base de datos.

Cómo verificar la creación desde el navegador

El flujo de prueba es directo:

  1. Recarga el navegador para que tome el script actualizado.
  2. Abre el inspector y coloca un breakpoint en handleSubmit.
  3. Llena el formulario con título, precio, categoría, descripción e imagen.
  4. Avanza paso a paso y revisa que productData coincida con la especificación.
  5. Confirma en la consola el console.log con el objeto retornado, incluido el nuevo id [11:50].

Cuando todo cuadra, el response.ok llega en true, el JSON de respuesta trae el producto completo y la integración entre repositorio, vista y API queda cerrada.

¿Cómo te fue conectando el formulario con tu repositorio? Cuéntame en los comentarios qué errores te aparecieron y cómo los resolviste.