Menu
CoddyTech

Rutas asíncronas

Parte de la sección Conceptos básicos de Express del Journey de Node.js de Coddy. Lección 18 de 20.

Un arreglo desaparece cuando se reinicia el servidor. Un archivo conserva los datos.

import { readFile } from 'node:fs/promises';

app.get('/api/forecast', async (req, res) => {
    const text = await readFile('data/forecast.json', 'utf8');
    res.json(JSON.parse(text));
});

Una ruta puede ser una función async que espera con await, en este caso a que termine readFile de node:fs/promises. Express 5 supervisa la promesa que devuelve la ruta: si se rechaza porque el archivo no existe o su JSON está dañado, el error llega a tu gestor de errores, como si se lanzara una excepción.

Sin await, tienes una promesa en lugar de los datos, y res.json(promise) envía {}. El nuevo data/recipes.json contiene las cuatro recetas.

challenge icon

Desafío

Fácil
  • Cada ruta de routes/recipes.js lee las recetas de data/recipes.json en cada solicitud.
  • POST guarda la nueva lista con writeFile.

Publica una receta y después envía GET /api/recipes, GET /api/recipes/5 y GET /api/recipes/99.

Pruébalo tú mismo

import express from 'express';
import { recipes } from '../data.js';

const router = express.Router();

// Cada etiqueta, una sola vez, en orden alfabético.
router.get('/tags', (req, res) => {
    const tags = new Set(recipes.flatMap((recipe) => recipe.tags));
    res.json([...tags].sort());
});

router.get('/', (req, res) => {
    res.json(recipes);
});

router.get('/:id', (req, res) => {
    const recipe = recipes.find((r) => r.id === Number(req.params.id));
    if (!recipe) {
        res.status(404).json({ error: 'No such recipe' });
        return;
    }
    res.json(recipe);
});

router.post('/', (req, res) => {
    const { title, tags } = req.body;
    if (!title) {
        res.status(400).json({ error: 'A recipe needs a title' });
        return;
    }
    const recipe = { id: recipes.length + 1, title, tags: tags ?? [] };
    recipes.push(recipe);
    res.status(201).json(recipe);
});

router.get('/:id/scale', (req, res) => {
    const recipe = recipes.find((r) => r.id === Number(req.params.id));
    if (!recipe) {
        res.status(404).json({ error: 'No such recipe' });
        return;
    }
    const by = Number(req.query.by);
    if (!Number.isFinite(by) || by <= 0) {
        res.status(400).json({ error: 'Scale by a positive number' });
        return;
    }
    if (!recipe.servings) {
        throw new Error(`Recipe ${recipe.id} has no servings`);
    }
    res.json({ title: recipe.title, servings: recipe.servings * by });
});

export default router;
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Conceptos básicos de Express