起步案例
路由设计
案例:通过该案例创建一个简单的 CRUD 接口服务,从而掌握 Express 的基础用法。
需求:实现对任务清单的 CRUD 接口服务。
- 查询任务列表:
GET /todos
- 根据 ID 查询单个任务:
GET /todos/:id
- 添加任务:
POST /todos
- 修改任务:
PATCH /todos
- 删除任务:
DELETE /todos/:id
const express = require('express');
const app = express();
const port = 3000;
app.get('/todos', (req, res) => {
res.send('get /todos');
});
app.get('/todos/:id', (req, res) => {
res.send('get /todos/:id');
});
app.post('/todos', function (req, res) {
res.send('post /todos');
});
app.patch('/todos/:id', function (req, res) {
res.send('patch /todos/:id');
});
app.delete('/todos/:id', function (req, res) {
res.send('delete /todos/:id');
});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`);
});
获取任务列表
const express = require('express');
const fs = require('fs');
const app = express();
const port = 3000;
app.get('/todos', (req, res) => {
fs.readFile('./db.json', 'utf8', (err, data) => {
if (err) {
return res.status(500).json({
err: err.message
});
}
const db = JSON.parse(data);
res.status(200).json(db.todos);
});
});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`);
});
根据 ID 获取单个任务
app.get('/todos/:id', (req, res) => {
fs.readFile('./db.json', 'utf8', (err, data) => {
if (err) {
return res.status(500).json({
err: err.message
});
}
const db = JSON.parse(data);
const todo = db.todos.find(todo => todo.id === Number(req.params.id));
if (!todo) {
return res.status(404).end();
}
res.status(200).json(todo);
});
});
封装 db 模块
// db.js
const fs = require('fs');
const path = require('path');
const { promisify } = require('util');
const readFile = promisify(fs.readFile);
const dbPath = path.join(__dirname, './db.json');
exports.getDb = async () => {
const data = await readFile(dbPath, 'utf8');
return JSON.parse(data);
};
假数据:
{
"todos": [
{
"id": 1,
"title": "吃饭"
},
{
"id": 2,
"title": "睡觉"
},
{
"id": 3,
"title": "写代码"
},
{
"id": 4,
"title": "看视频"
}
],
"users": []
}
// app.js
const express = require('express');
const { getDb } = require('./db');
const app = express();
const port = 3000;
app.get('/todos', async (req, res) => {
try {
const db = await getDb();
res.status(200).json(db.todos);
} catch (err) {
res.status(500).json({
err: err.message
});
}
});
app.get('/todos/:id', async (req, res) => {
try {
const db = await getDb();
const todo = db.todos.find(todo => todo.id === Number(req.params.id));
if (!todo) {
return res.status(404).end();
}
res.status(200).json(todo);
} catch (err) {
res.status(500).json({
err: err.message
});
}
});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`);
});
添加任务
app.post('/todos', async (req, res) => {
try {
const todo = req.body;
if (!todo.title) {
return res.status(422).json({
err: 'The field title is required!'
});
}
const db = await getDb();
const lastTodo = db.todos[db.todos.length - 1];
todo.id = lastTodo ? lastTodo.id + 1 : 1;
db.todos.push(todo);
await saveDb(db);
res.status(201).json(todo);
} catch (err) {
res.status(500).json({
err: err.message
});
}
});
修改任务
app.patch('/todos/:id', async (req, res) => {
try {
const todo = req.body;
const db = await getDb();
const ret = db.todos.find(todo => todo.id === Number(req.params.id));
if (!ret) {
return res.status(404).end();
}
Object.assign(ret, todo);
await saveDb(db);
res.status(200).json(ret);
} catch (err) {
res.status(500).json({
err: err.message
});
}
});
删除任务
app.delete('/todos/:id', async (req, res) => {
try {
const todoId = Number(req.params.id);
const db = await getDb();
const index = db.todos.findIndex(todo => todo.id === todoId);
if (index === -1) {
return res.status(404).end();
}
db.todos.splice(index, 1);
await saveDb(db);
res.status(204).end();
} catch (err) {
res.status(500).json({
err: err.message
});
}
});