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.
Desafío
Fácil- Cada ruta de
routes/recipes.jslee las recetas dedata/recipes.jsonen cada solicitud. POSTguarda la nueva lista conwriteFile.
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;
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.