Menu
CoddyTech

Una página que llama a la API

Parte de la sección API REST del Journey de Node.js de Coddy. Lección 21 de 25.

Una página llama a tu API con fetch. Un POST necesita tres opciones: método, encabezados y cuerpo. Convierte el objeto JavaScript en texto JSON para el cuerpo y etiqueta ese texto como application/json.

const response = await fetch('/api/books', {
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify({title: title}),
});
const data = await response.json();

El primer await recibe la respuesta HTTP. El segundo lee su cuerpo JSON. response.ok te indica si su estado está dentro del rango de éxito. Un estado como 400 o 409 no rechaza la promesa de fetch; devuelve una respuesta cuyo ok es false. El código del formulario y de la lista ya está proporcionado; céntrate en enviar la solicitud y gestionar el resultado.

La variable message proporcionada hace referencia al párrafo de mensajes de la página. Asigna texto a su textContent para mostrarlo, o una cadena vacía para borrarlo:

message.textContent = data.error.message;
// Bórralo después de que se complete correctamente:
message.textContent = '';

La página y la API comparten un mismo origen, así que esta llamada no necesita permiso CORS. FormData codifica un formulario de forma distinta a JSON; usa texto JSON porque esta API utiliza express.json().

challenge icon

Desafío

Fácil

Tu API todavía no tiene interfaz. Añádele una página sencilla, servida por el mismo servidor, cuyo formulario agregue tareas a través de la API.

  1. En server.js, sirve la carpeta public con express.static, para que GET / devuelva public/index.html.
  2. En public/index.html, el listener de envío ya lee el título. Haz que envíe la nueva tarea a la API:
    • Usa la variable title proporcionada, que contiene el texto de entrada.
    • Envíala con fetch('/api/tasks', ...) como una solicitud POST.
    • El cuerpo es texto JSON creado con JSON.stringify, como {"title":"Water the plants"}.
    • La solicitud necesita el encabezado 'Content-Type': 'application/json' en la opción headers de fetch; de lo contrario, express.json() no leerá el cuerpo.
  3. Si la respuesta es correcta (su propiedad ok es true para cualquier estado entre 200 y 299), limpia el formulario con form.reset(), vacía #message y llama a load() para que la lista muestre la nueva tarea.
  4. De lo contrario, el cuerpo de la respuesta tiene el formato de error visto antes, por ejemplo:
    { "error": { "code": "conflict", "message": "A task with this title already exists" } }
    Muestra su message en el párrafo #message.

Las comprobaciones ejecutan el script de esta página proporcionado con un pequeño formulario simulado y la API real de la lección. Envían una tarea y luego un duplicado, y después inspeccionan la lista, el formulario y el mensaje. Prueba también la página real junto al editor.

Pruébalo: envía GET /. La página se abre en la vista de página con las 3 tareas iniciales. Escribe "Water the plants" y pulsa Añadir: el campo de entrada se vacía y la tarea aparece al final de la lista. Escribe "Water the plants" de nuevo y pulsa Añadir: la lista permanece igual y aparece "A task with this title already exists" debajo del formulario.

Pruébalo tú mismo

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Tasks</title>
</head>
<body>
    <h1>Tasks</h1>
    <ul id="list"></ul>
    <form id="add">
        <input name="title" placeholder="New task" required>
        <button>Add</button>
    </form>
    <p id="message"></p>
    <script>
        const list = document.querySelector('#list');
        const form = document.querySelector('#add');
        const message = document.querySelector('#message');

        async function load() {
            const response = await fetch('/api/tasks?limit=50');
            const page = await response.json();
            list.replaceChildren(...page.items.map((task) => {
                const item = document.createElement('li');
                item.textContent = (task.done ? '[x] ' : '[ ] ') + task.title;
                return item;
            }));
        }

        form.addEventListener('submit', async (event) => {
            event.preventDefault();
            const title = form.elements.title.value;
            // Send the title to POST /api/tasks as JSON. On success clear
            // the form and load() again; on an error show its message.
        });

        load();
    </script>
</body>
</html>

Todas las lecciones de API REST

Practica por tu cuenta: Playground de Express