Menu
CoddyTech

Route asincrone

Fa parte della sezione Fondamenti di Express del percorso Node.js di Coddy. Lezione 21 di 23.

Un array scompare quando il server si riavvia. Un file conserva i dati.

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 route può essere una funzione async che attende con await, in questo caso readFile da node:fs/promises. Express 5 monitora la promise restituita dalla route: se viene rifiutata, perché il file manca o il suo JSON non è valido, l'errore viene inviato al tuo gestore degli errori, proprio come un'eccezione.

Senza await ottieni una promise invece dei dati e res.json(promise) invia {}. Il nuovo data/recipes.json contiene le quattro ricette.

challenge icon

Sfida

Facile

Un array in memoria viene perso ogni volta che il server si riavvia. Conserva invece le ricette in un file: data/recipes.json, che contiene già le quattro ricette.

  1. In routes/recipes.js, importa readFile e writeFile da node:fs/promises e smetti di importare recipes da ../data.js.
  2. Scrivi una funzione di supporto, loadRecipes(), una funzione asincrona che legge data/recipes.json e restituisce l’elenco analizzato. Le lezioni successive la useranno con quel nome.
  3. Rendi async tutte le route del file e inizia ciascuna di esse attendendo loadRecipes(): /tags, l’elenco, una ricetta, la route POST e quella per la scalatura.
  4. Nella route POST, dopo aver aggiunto la nuova ricetta all’elenco, riscrivi l’intero elenco in data/recipes.json con writeFile, come testo JSON.
  5. La route per la scalatura continua a generare un errore per una ricetta senza porzioni, ora dall’interno di una funzione asincrona. Express 5 passa quell’errore al tuo gestore degli errori come prima, quindi la risposta è ancora 500 e {"error": "Something went wrong"}. Non intercettarlo nella route.

Prova: premi «Esegui» e invia /api/recipes: le stesse quattro ricette, ora lette dal file. Seleziona POST e invia {"title": "Gazpacho", "tags": ["vegan", "soup"]} a /api/recipes: stato 201 e la ricetta con "id": 5. Invia /api/recipes/5: Gazpacho. Invia /api/recipes/99: stato 404. Poi invia POST {"title": "Toast"}, che non ha porzioni e diventa la ricetta 6, e invia /api/recipes/6/scale?by=2: stato 500 e {"error":"Something went wrong"}. Se vedi {} invece dei tuoi dati, manca un await.

Provalo tu

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

const router = express.Router();

// Ogni tag, una sola volta, in ordine alfabetico.
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 iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Fondamenti di Express

Esercitati da solo: Playground Express