Menu
CoddyTech

비동기 라우트

Coddy Node.js 여정의 Express 기초 섹션에 포함된 레슨. 20개 중 18번째.

배열은 서버가 다시 시작되면 사라집니다. 파일은 데이터를 보존합니다.

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로 기다릴 수 있으며, 여기서는 node:fs/promises의 readFile을 기다립니다. Express 5는 경로가 반환하는 프라미스를 감시합니다. 파일이 없거나 JSON이 잘못되어 프라미스가 거부되면, throw가 발생했을 때처럼 오류가 오류 처리기로 전달됩니다.

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 기초의 모든 레슨