Menu
CoddyTech

Asenkron Rotalar

Coddy'nin Node.js Journey'sinin Express Temelleri bölümünün bir parçası. Ders 21 / 23.

Sunucu yeniden başladığında dizi kaybolur. Dosya verileri saklar.

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));
});

Bir rota, burada node:fs/promises içinden readFile için await ile bekleyen bir async işlev olabilir. Express 5, rotanın döndürdüğü promise'i izler: dosya bulunmadığı veya JSON'u bozuk olduğu için reddedilirse hata, bir fırlatma gibi hata işleyicinize gider.

await olmadan veriler yerine bir promise tutarsınız ve res.json(promise), {} gönderir. Yeni data/recipes.json dört tarifi içerir.

challenge icon

Görev

Kolay

data/recipes.json; bu dosyada zaten dört tarif bulunuyor.

  1. routes/recipes.js dosyasında node:fs/promises içinden readFile ve writeFile içe aktar, ../data.js dosyasından recipes içe aktarmayı bırak.
  2. loadRecipes() adında tek bir yardımcı işlev yaz. Bu, data/recipes.json dosyasını okuyan ve ayrıştırılmış listeyi döndüren bir async işlev olsun. Sonraki derslerde bu işlev aynı adla kullanılacak.
  3. Dosyadaki her rotayı async yap ve her birine loadRecipes() işlevini await ederek başla: /tags, liste, tek bir tarif, POST ve ölçeklendirme rotası.
  4. POST rotasında, yeni tarifi listeye ekledikten sonra tüm listeyi JSON metni olarak writeFile ile data/recipes.json dosyasına geri yaz.
  5. Ölçeklendirme rotası, porsiyon sayısı olmayan bir tarif için hâlâ hata fırlatır; artık bunu bir async işlevin içinden yapar. Express 5 bu hatayı önceden olduğu gibi hata işleyicine iletir, dolayısıyla yanıt yine 500 ve {"error": "Something went wrong"} olur. Rotada bu hatayı yakalama.

Deneyin: “Çalıştır” düğmesine bas ve /api/recipes adresine istek gönder: artık dosyadan okunan aynı dört tarif. POST'u seç ve {"title": "Gazpacho", "tags": ["vegan", "soup"]} içeriğini /api/recipes adresine gönder: durum kodu 201 ve "id": 5 olan tarif. /api/recipes/5 adresine istek gönder: Gazpacho. /api/recipes/99 adresine istek gönder: durum kodu 404. Ardından porsiyon sayısı olmayan ve 6 numaralı tarif olacak {"title": "Toast"} içeriğini POST ile gönder ve /api/recipes/6/scale?by=2 adresine istek gönder: durum kodu 500 ve {"error":"Something went wrong"}. Verilerin yerine {} görüyorsan bir await eksiktir.

Kendin dene

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

const router = express.Router();

// Her etiket, bir kez, alfabetik sırayla.
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 iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Express Temelleri bölümündeki tüm dersler

Kendi başına pratik yap: Express playground