路由及其他要求:
查询任务列表:GET /todos
根据ID查询单个任务:GET /todos/:id
添加任务:POST /todos
修改任务:PATCH /todos
删除任务:DELETE /todos/:id
假设任务列表db.json如下:
{
"todos": [
{
"id": 001,
"title": "research"
},
{
"id": 002,
"titlo": "write papers"
},
{
"id": 003,
"title": "coding"
}
],
"users": []
}
实现过程:
在发起多个请求的过程中,会出现重复获取任务列表的情况,故对其进行一个简单的封装。对db.json的操作封装到db.js文件内.
db.js:
const fs = require('fs')
const { promisify } = require('util') // util所提供的promisify方法能够把callback这种形式的异步api转换成promise的方式
const path = require('path')
const readFile = promisify(fs.readFile)
const dbPath = path.join(__dirname, './db.json') //dirname代表当前所在文件路径
//path.join()方法使用特定于平台的分隔符作为定界符将所有给定的 path 片段连接在一起,然后规范化生成的路径。
exports.getDb = async () => {
const data = await readFile(dbPath, 'utf8')
return JSON.parse(data)
}
主体代码app.js:
// import express from 'express'
const express = require('express')
const fs = require('fs')
const { getDb, saveDb } = require('./db')
const app = express()
// 配置解析表单请求体:application/json
app.use(express.json()) //把客户端提交过来的数据按照JSON格式转换成js对象
// 配置解析表单请求体:application/x-www-form-urlencoded
app.use(express.urlencoded())
/* 查询任务列表 */
app.get('/todos', async (req, res) => {
try { //异常捕获
const db = await getDb()
res.status(200).json(db.todos)
} catch (err) {
res.status(500).json({
error: err.message
})
}
})
/* 根据ID查询单个任务 */
app.get('/todos/:id', async (req, res) => {
// console.log(typeof req.params.id)
try {
const db = await getDb()
const todo = db.todos.find(todo => todo.id === Number.parseInt(req.params.id))
if (!todo) {
return res.status(404).end()
}
res.status(200).json(todo)
} catch (err) {
res.status(500).json({
error: err.message
})
}
})
/* 添加任务 */
app.post('/todos', async (req, res) => {
try {
// 1. 获取客户端请求体参数
// console.log(req.body)
const todo = req.body
// 2. 数据验证
if (!todo.title) {
return res.status(422).json({
error: 'The field title is required.'
})
}
// 3. 数据验证通过,将数据存储到db中
const db = await getDb()
const lastTo = db.todos[db.todos.length - 1]
todo.id = lastTo ? lastTo.id + 1 : 1
db.todos.push(todo)
// 把db重新写入到db.json文件内
await saveDb(db)
// 发送响应
res.status(200).json(todo)
} catch (err) {
res.status(500).json({
error: err.message
})
}
})
/* 修改任务 */
app.patch('/todos/:id', async (req, res) => {
try {
//1. 获取数据
const todo = req.body
//2. 查找到要修改的列表项
const db = await getDb()
const ret = db.todos.find(todo => todo.id === Number.parseInt(req.params.id))
if(!ret){
return res.status(404).end()
}
Object.assign(ret, todo) //把todo内的属性内容复制到ret内,返回ret对象。如果有同名属性的话,后面的属性值会覆盖前面的属性值。具体可看ES6官方文档
await saveDb(db)
res.status(200).json(ret)
} catch (err) {
res.status(500).json({
error: err.message
})
}
res.send('patch /todos')
})
/* 删除任务 */
app.delete('/todos/:id', async (req, res) => {
try {
//1. 拿到要删除的任务的id
const todoId = Number.parseInt(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) //从索引index开始,删除1项数据
await saveDb(db)
res.status(204).end()
} catch (err) {
res.status(500).json({
error: err.message
})
}
})
app.listen(3000, () => {
console.log('Server running at http://localhost:3000')
})
效果
查询任务列表

注意查看返回的状态码(200)
根据ID查询单个任务

注意查看返回的状态码(200
)
添加任务

注意查看返回的状态码(200)
修改任务

注意查看返回的状态码(200)
删除任务

注意查看返回的状态码(204)