Menu
CoddyTech

المسارات غير المتزامنة

جزء من قسم أساسيات Express في رحلة Node.js على Coddy. الدرس 18 من 20.

تختفي المصفوفة عند إعادة تشغيل الخادم. أما الملف فيحتفظ بالبيانات.

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

يمكن أن يكون المسار دالة async تنتظر باستخدام await، وهنا تنتظر readFile من node:fs/promises. يراقب Express 5 الوعد الذي تعيده الدالة: إذا رُفض، بسبب فقدان الملف أو تلف JSON فيه، ينتقل الخطأ إلى معالج الأخطاء لديك، كما يحدث عند طرح استثناء.

من دون await، ستحصل على وعد بدلًا من البيانات، وسيُرسل res.json(promise) القيمة {}. يحتوي الملف الجديد data/recipes.json على الوصفات الأربع.

challenge icon

التحدي

سهل
  • يقرأ كل مسار في routes/recipes.js الوصفات من data/recipes.json عند كل طلب.
  • يحفظ POST القائمة الجديدة مرة أخرى باستخدام writeFile.

أرسل وصفة، ثم أرسل GET /api/recipes وGET /api/recipes/5 وGET /api/recipes/99.

جرّب بنفسك

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

const router = express.Router();

// كل وسم مرة واحدة، بترتيب أبجدي.
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 iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس أساسيات Express