express的使用笔记 2 请求对象与响应对象 、 增删改查demo

Express不对Node.js已有的特性进行二次抽象,只是在它之上扩展了web应用所需的基本功能。内部使用的依旧是http模块,请求对象继承字http.IncomingMessage,响应对象继承自http.ServerResponse,所以node.js官网中的对应的方法可以通用

1.请求对象

2.响应对象
除了response.send(),response.write()也可以发送数据
也可以直接在结束响应的同时发送数据response.send(1)


路由设计Demo练习:
需求描述:实现对任务清单的CRUD接口服务
·查询任务列表 ---》GET/todos
·根据ID查询单个任务 ----》GET/todos/:id
·添加任务 ----》POST.todos
·修改任务 ---》PATCH/todos/:id
·删除任务 ---》DELETE/todos/:id

动态参数可以通过模板字符的写法,从请求参数中获取

app.get('/todos', (req, res) => {
    res.send('get/todos');
});
// 动态路由的使用
app.get('/todos/:id', (req, res) => {
    res.send(`get/todos/${req.params.id}`);
});
app.post('/todos', (req, res) => {
    res.send(`post/todos`);
});
app.patch('/todos/:id', (req, res) => {
    res.send(`patch/todos`);
});
app.delete('/todos', (req, res) => {
    res.send(`delete/todos/${req.params.id}`);
});

express不限制数据的存储位置,模拟的时候咱们放在json文件中吧~

// 1.引入fs模块
const fs = require("fs");
const app = express();
// 2. 尽量使用异步读取json文件的数据,
// 异步:readFile('json文件路径','utf8',回调函数接口两个参数,一个err,一个data)
// 同步:readFileSync如果使用同步的话,则不接受回调函数作为参数,且会阻塞执行线程直到文件读取完成
//--------------接口1获取任务列表---------
// 同步写法如下:
app.get("/todos", (req, res) => {
  try {
    const data = fs.readFileSync("./db.json", "utf8");
    const db = JSON.parse(data);
    res.status(200).json(db.todos);
  } catch (err) {
    // 如果发生错误,返回500状态码并发送错误信息
    res.status(500).json({ error: err.message });
  }
});
// 异步写法如下:
app.get("/todos", (req, res) => {
  const data = fs.readFile("./db.json", "utf8", (err, data) => {
    if (err) {
      // 如果发生错误,返回500状态码并发送错误信息
      return res.status(500).json({ error: err.message });
    }
    const db = JSON.parse(data);
    res.status(200).json(db.todos);
  });
});

//--------------接口2根据参数传递的ID获取对应的列表的数据项---------
app.get("/todos/:id", (req, res) => {
  //   res.send(`get/todos/${req.params.id}`);
  fs.readFile("./db.json", "utf8", (err, data) => {
    if (err) {
      return res.status(500).send({
        error: err.message,
      });
    }
    const db  = JSON.parse(data);
    const todo = db.todos.find(todo=>todo.id===Number.parseInt(req.params.id))
   if (!todo) {
      return res.status(404).send("找不到该条数据项");
    }
    res.status(200).send(todo)
  });
});

插曲:
每次都要写fs.readFile ,json.parse太麻烦了,封装一下
将callback形式异步APi,通过node.js中的util工具中的promisify转换成promise的形式

  1. 根目录下创建db.js,进行代码封装
const fs = require("fs");
const { promisify } = require("util");
const path = require("path");
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);
};

  1. 在app.js中引入使用,且修改
const express = require("express");
// 1.引入fs模块
const fs = require("fs");
//2. 引入db.js中封装好的方法
const { getDB } = require("./db");
const app = express();
app.get("/todos", async (req, res) => {
  try {
    const db = await getDB();
    res.status(200).json(db.todos);
  } catch (err) {
    return res.status(500).json({ error: err.message });
  }
});
// 动态路由的使用
app.get("/todos/:id", async (req, res) => {
  try {
    const db = await getDB();
    const todo = db.todos.find((todo) => todo.id === Number.parseInt(req.params.id));
    if (!todo) {
      return res.status(404).send("找不到该条数据项");
    }
    res.status(200).send(todo);
  } catch (err) {
    return res.status(500).json({ error: err.message });
  }
});

//--------------接口3 写入列表新数据项---------
第三个接口,post请求体,1)获取客户端请求体参数 2)数据验证 3)验证通过则把数据储存到DB中 4)发送响应,告知成功

1)获取客户端请求体参数
a) application/json格式:
在app实例中挂载一下express.json()来配置解析表单请求体,然后通过request.body获取用户传递的请求体参数;

app.use(express.json())

b) application/x-www-form-urlencoded格式:

app.use(express.urlencoded())

2)获取客户端请求体参数 与 数据验证

// 1.引入express
const express = require("express");
//2. 引入db.js中封装好的方法
const { getDB, saveDB } = require("./db");
const app = express();
app.use(express.json());
app.use(express.urlencoded());

// 写入数据 req.body获取请求体数据, 配置先
app.post("/todos", async (req, res) => {
  try {
    const db = await getDB();
    const reqBd = req.body;
    console.log(req.body, "请求体");
    // 如果传递的对象中不包含title,则提示用户输入不符合的参数了
    if (!reqBd.title) {
      return res.status(422).send({ error: "The field title is required" });
    }
    const lastTodoItem = db.todos[db.todos.length - 1];
    db.todos.push({
      id: lastTodoItem ? lastTodoItem.id + 1 : 1,
      title: reqBd.title
    });
    await saveDB(db)
    res.status(200).send("添加成功!");
  } catch (err) {
    res.status(500).send({ error: err.message });
  }
});

3)存储封装

const fs = require("fs");
const { promisify } = require("util");
const path = require("path");
const readFile = promisify(fs.readFile);
const dbPath = path.join(__dirname, "./db.json");
const writeFile = promisify(fs.writeFile) //引入写入模块方法
// 读取封装
exports.getDB = async () => {
  const data = await readFile(dbPath, "utf8");
  return JSON.parse(data);
};
// 写入封装
exports.saveDB = async (db) => {
    const data = JSON.stringify(db)
    // 如果需要Json文件渲染有格式化则传递第三个参数,表示格式的空格
    // const data = JSON.stringify(db,null,'  ')
    await writeFile(dbPath,data)
};


//--------------接口4 编辑列表数据项---------

app.patch("/todos/:id", async (req, res) => {
  // 1.获取用户传入的数据
  // 2.找到与之匹配的数据项
  // 3.进行替换且告知客户端
  try {
    const reqBd = req.body;
    const db = await getDB();
    const todoItem = db.todos.find(
      (todo) => todo.id === Number.parseInt(req.params.id)
    );
    if (!todoItem) {
      return res.status(422).send("没查询到对应的数据项,无法进行修改~");
    }
    // Object.assign(要被修改的数据项,传入的数据项且与被修改匹配的数据项) 如果有找到就替换,没找到就新增一条,但我们的逻辑中不允许新增,直接return报错提示,如上
    Object.assign(todoItem, reqBd);
    await saveDB(db);
    res.status(200).send("修改成功!");
  } catch (err) {
    res.status(500).send({ error: err.message});
  }
});

//--------------接口5 删除列表数据项---------

app.delete("/todos/:id", async (req, res) => {
  //   res.send(`delete/todos/${req.params.id}`);
  try {
    const db = await getDB();
    const todoItemIndex = db.todos.findIndex(
      (todo) => todo.id === Number.parseInt(req.params.id)
    );
    if (todoItemIndex===-1) {
      res.status(422).send("没有您要删除的数据项");
    }
    //根据下标删除 
    db.todos.splice(todoItemIndex,1);
    await saveDB(db);
    res.status(200).send('删除成功')
  } catch (err) {
    res.status(500).send({ error: err.message });
  }
});


posted @ 2024-10-11 17:13  JocelynFung  阅读(8)  评论(0编辑  收藏  举报
Live2D 看板娘 / Demo