Web 开发 27

1 路由router引入语法解释

javascript 复制代码
router.get("/stories", (req, res) => {
  Story.find({})
    .then((stories) => res.send(stories));
});

语法分解

1. 路由定义

router.get("/stories", (req, res) => { ... });

  • router.get() - Express.js 中定义 GET 请求路由的方法
  • "/stories" - 路由路径,客户端访问此路径时触发回调函数
  • (req, res) => { ... } - 路由处理函数(箭头函数)

2. 参数说明

  • req - 请求对象(Request Object),包含客户端发送的请求信息
  • res - 响应对象(Response Object),用于向客户端发送响应

3. 数据库查询

Story.find({})

  • Story - Mongoose 数据模型(基于 MongoDB)
  • .find({}) - Mongoose 查询方法,查找所有文档(空对象 {} 表示无条件)
  • 返回一个 Promise 对象

4. Promise 处理

.then((stories) => res.send(stories))

  • .then() - Promise 的成功回调方法
  • (stories) => res.send(stories) - 箭头函数,参数 stories 是查询结果
  • res.send(stories) - 将查询结果发送给客户端

执行流程

  1. 路由匹配 :收到 GET 请求到 /stories
  2. 数据库查询 :执行 Story.find({}) 查找所有故事
  3. 异步处理:等待数据库查询完成(Promise)
  4. 结果处理 :查询完成后执行 .then() 回调
  5. 响应发送 :使用 res.send() 将数据返回客户端

等价的传统写法

javascript 复制代码
// 使用 function 关键字的等价写法
router.get("/stories", function(req, res) {
  Story.find({})
    .then(function(stories) {
      res.send(stories);
    });
});

// 或者使用 async/await 语法
router.get("/stories", async (req, res) => {
  try {
    const stories = await Story.find({});
    res.send(stories);
  } catch (error) {
    res.status(500).send(error);
  }
});

这是典型的 Express.js + Mongoose 构建 REST API 的模式。

2关于前端向后端发送 GET 请求并在后端获取请求参数

前端部分代码解释

  • 代码中使用了 useEffect 钩子(这是 React 中的一个钩子函数,用于在组件渲染后执行副作用操作,比如发送网络请求)。
  • 调用 get("/api/comment", { parent: props._id }) 是向前端的 /api/comment 接口发送 GET 请求,并且在请求中附带了一个查询参数,参数名为 parent,值为 props._id(这里的 props._id 应该是父级故事的唯一标识)。
  • 然后通过 .then 方法处理请求成功后的回调,将获取到的评论数据 commentssetComments 方法设置到组件的状态中,以便在组件中渲染评论。

后端如何获取参数

在后端(通常是基于 Node.js 的 Express 等框架),可以通过请求对象 req 来获取前端发送过来的查询参数。

  • 对于 GET 请求中附带的查询参数(也就是像这里通过在请求中传递 { parent: props._id } 这样的方式),可以通过 req.query 对象来访问。
  • 所以要获取前端发送的 parent 参数,就可以使用 req.query.parent,这样后端就能拿到父级故事的 _id,进而可以根据这个 _id 去数据库等地方查询相关的评论数据等后续操作。

扩展

在 HTTP 协议中,GET 请求的参数通常是通过 URL 的查询字符串(Query String)来传递的,格式一般是 ?key1=value1&key2=value2 这样附加在 URL 后面。

前端的一些请求库(比如这里可能用到的类似 axios 或者自定义的 get 方法)会将传递的参数对象(如 { parent: props._id })转换为查询字符串的形式附加到 URL 上,然后发送给后端。

而后端的框架(如 Express)会自动解析 URL 中的查询字符串,并将解析后的结果存储在 req.query 对象中,方便开发者获取和使用这些参数来进行业务逻辑处理。

3 实现一个 GET /comment 的接口

这是让你实现一个 GET /comment 的接口,目的是根据前端传来的 parent 参数,从数据库(推测用的是 MongoDB,因为提到了 mongo - snippets)中查询对应的评论数据。下面是具体步骤:

步骤 1:理解需求

前端通过 GET 请求,把父级内容的标识(parent 参数)传递到 /comment 接口,后端需要接收这个参数,然后从数据库里找出 parent 字段等于该参数值的评论文档。

步骤 2:获取前端传递的参数

根据提示 "req.query 包含 GET 请求的内容",在后端(比如用 Node.js + Express 框架),你可以通过 req.query.parent 来获取前端传来的 parent 参数值。

步骤 3:查询数据库

假设你用 Mongoose(MongoDB 的 Node.js 驱动工具)来操作数据库,并且有一个 Comment 模型(对应 comment 集合)。你需要在代码中找到标注 /* input the parent parameter here */ 的地方,替换成查询逻辑。

  • 方法一(使用对象查询):
javascript 复制代码
Comment.find({ parent: req.query.parent })
  .then(comments => {
    // 处理查询到的评论数据,比如返回给前端
    res.json(comments);
  })
  .catch(err => {
    // 处理错误
    res.status(500).json({ error: err.message });
  });
  • 方法二(使用 where 方法):
javascript 复制代码
Comment.find({})
  .where('parent').equals(req.query.parent)
  .then(comments => {
    res.json(comments);
  })
  .catch(err => {
    res.status(500).json({ error: err.message });
  });

完整示例(基于 Express 和 Mongoose)

首先确保你已经设置好了 Express 应用和 Mongoose 连接,并且定义了 Comment 模型。然后编写路由:

javascript 复制代码
const express = require('express');
const router = express.Router();
const Comment = require('../models/Comment'); // 假设 Comment 模型在 ../models/Comment.js 中

router.get('/comment', (req, res) => {
  // 这里就是要替换 /* input the parent parameter here */ 的地方
  Comment.find({ parent: req.query.parent })
    .then(comments => {
      res.json(comments);
    })
    .catch(err => {
      res.status(500).json({ error: err.message });
    });
});

module.exports = router;

这样,当前端发送带有 parent 参数的 GET 请求到 /api/comment(假设路由挂载在 /api 下)时,后端就能查询到对应的评论并返回给前端了。

4 直接查看请求负载(Request Payload)这样的可视化窗口

其实就是图中的白色小窗。

图中下方白色小窗是 请求负载(Request Payload) 展示窗口,它用于呈现前端向后端发送 POST 请求时携带的数据内容。

在前端代码中,addComment 函数构建了一个包含 parentcontent 字段的对象 body,并通过 post 方法将其发送到 /api/comment 接口 。其中,parent 表示父级内容的标识(比如文章 ID 等),content 是评论的具体内容,value 就是用户输入的评论文字。

白色小窗里显示了实际发送的请求负载示例 {parent: 0, content: "I don't :("},可以看到具体的 parent 值为 0content 值为 "I don't :(" ,这是在模拟实际发送请求时携带的数据结构和数据内容。

在后端开发中,了解请求负载的结构非常重要,这样才能正确地解析和处理前端发送过来的数据,比如将评论内容存储到数据库对应的字段中,或者基于 parent 字段进行关联查询等操作 。

【怎么在vscode里面查看这个白色窗口的】

在 VSCode 中本身没有直接查看请求负载(Request Payload)这样的可视化窗口,不过你可以通过以下几种方式间接获取类似信息:

借助浏览器开发者工具

  1. 打开开发者工具 :在 Chrome、Firefox 等主流浏览器中,按下 F12 键或者通过菜单找到 "开发者工具" 选项打开它。
  2. 切换到 Network 面板 :在开发者工具界面中,点击 Network(网络)选项卡。
  3. 触发 POST 请求:在你的网页应用中执行触发 POST 请求的操作,比如点击提交评论按钮等。
  4. 查看请求详情 :在 Network 面板中找到对应的 POST 请求,点击它,然后在右侧展开的详情中找到 Payload 或者 Request Body 部分,就能看到发送的请求负载内容了。

使用 VSCode 插件(以 REST Client 插件为例)

  1. 安装插件 :在 VSCode 左侧的插件市场中,搜索 REST Client 插件,然后点击安装并重启 VSCode 让插件生效。
  2. 创建请求文件 :在 VSCode 中新建一个文件,后缀名可以设为 .http 或者 .rest ,比如 comments.http
  3. 编写请求内容:按照 REST Client 插件的语法格式编写 POST 请求,示例如下:
bash 复制代码
POST http://localhost:3000/api/comment HTTP/1.1
Content-Type: application/json

{
    "parent": 0,
    "content": "This is a test comment"
}

这里的 URL 需要根据你实际的后端接口地址进行修改,Content-Type 根据实际发送的数据格式设置,常见的有 application/jsonapplication/x-www-form-urlencoded 等。

  1. 发送请求并查看 :点击请求代码块旁边的 Send Request 按钮发送请求,在下方的 Response 区域就能看到请求的响应结果,同时在请求发送时,你可以通过浏览器开发者工具或者后端日志等方式确认请求负载内容。

查看后端日志

如果是在后端接收和处理这个 POST 请求,你可以在后端代码中添加日志输出,以 Node.js + Express 为例:

javascript 复制代码
const express = require('express');
const app = express();
app.use(express.json()); // 用于解析 application/json 格式的请求体

app.post('/api/comment', (req, res) => {
    console.log('Received POST request payload:', req.body);
    // 其他处理逻辑,比如保存评论到数据库等
    res.send('Comment received successfully');
});

const port = 3000;
app.listen(port, () => {
    console.log(`Server running on port ${port}`);
});

运行后端程序后,在 VSCode 的终端中就能看到输出的请求负载内容了。

5 连接数据库学习小结

这是对一段学习内容的回顾(Recap),以下是详细解释和扩展:

1. Understand database structure, schemas, models(理解数据库结构、模式、模型)

  • 解释
    • 数据库结构:指数据库的组织方式,比如关系型数据库(如 MySQL)是通过表(Tables)、行(Rows)、列(Columns)来组织数据;非关系型数据库(如 MongoDB)是通过集合(Collections)、文档(Documents)等方式组织数据。
    • 模式(Schemas):在数据库中,模式定义了数据的结构和约束。例如在 MongoDB 中,Mongoose 库的模式(Schema)可以定义文档有哪些字段、字段的类型(字符串、数字等)、是否必填等规则;在关系型数据库中,表的结构(字段名、数据类型、主键外键等)也属于模式的范畴。
    • 模型(Models):模型是基于模式创建的,它是与数据库交互的接口。通过模型可以进行数据的增、删、改、查等操作。比如在 Mongoose 中,基于 Schema 创建的 Model 可以用来查询集合中的文档。
  • 扩展 :以 MongoDB + Mongoose 为例,假设要存储用户数据,先定义 Schema,指定有 username(字符串,必填)、age(数字)等字段;然后基于该 Schema 创建 User 模型,之后就可以用 User.find() 来查询所有用户,用 User.create() 来创建新用户。

2. Hook remote mongodb instances to our nodejs app(将远程 MongoDB 实例连接到我们的 Node.js 应用)

  • 解释:Node.js 应用需要连接到 MongoDB 数据库才能进行数据操作。如果 MongoDB 数据库是部署在远程服务器上的(即远程实例),就需要在 Node.js 代码中配置正确的连接字符串(包含远程服务器的地址、端口、数据库名、认证信息等),来建立与远程 MongoDB 的连接。
  • 扩展:使用 Mongoose 库的话,连接代码大致如下:
javascript 复制代码
const mongoose = require('mongoose');
mongoose.connect('mongodb://<username>:<password>@<remote-server-ip>:<port>/<database-name>', {
  useNewUrlParser: true,
  useUnifiedTopology: true
})
  .then(() => console.log('Connected to remote MongoDB'))
  .catch(err => console.error('Connection error', err));

这里的连接字符串包含了远程 MongoDB 的认证、地址等信息,通过 mongoose.connect 方法建立连接。

3. Interact with database via an api(通过 API 与数据库交互)

  • 解释:不是直接在 Node.js 应用中写数据库操作代码供前端调用,而是封装一套 API(应用程序编程接口)。前端通过调用这些 API(比如发送 HTTP 请求到特定的接口),由 API 来处理与数据库的交互(增删改查等)。
  • 扩展 :比如用 Node.js + Express 框架搭建后端 API 服务。定义一个 /api/users 的 GET 接口,用于获取所有用户数据,在这个接口的处理函数中,使用之前创建的 User 模型查询数据库,然后将结果返回给前端。代码示例:
javascript 复制代码
const express = require('express');
const router = express.Router();
const User = require('./models/User'); // 假设 User 模型在 ./models/User.js 中

router.get('/api/users', async (req, res) => {
  try {
    const users = await User.find();
    res.json(users);
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

module.exports = router;

前端发送 GET 请求到 http://your-server.com/api/users 就能获取到用户数据。

4. Use that api in the frontend(在前端使用该 API)

  • 解释:前端(比如 React、Vue 等框架开发的页面)通过 HTTP 请求(如 fetch、axios 等工具)调用后端提供的 API,来获取或操作数据,然后将数据展示在页面上或者进行其他交互。
  • 扩展 :以 React 为例,使用 fetch 调用上面的 /api/users 接口:
javascript 复制代码
import React, { useEffect, useState } from 'react';

function UserList() {
  const [users, setUsers] = useState([]);

  useEffect(() => {
    fetch('http://your-server.com/api/users')
      .then(response => response.json())
      .then(data => setUsers(data))
      .catch(err => console.error('Error fetching users', err));
  }, []);

  return (
    <ul>
      {users.map(user => (
        <li key={user._id}>{user.username}</li>
      ))}
    </ul>
  );
}

export default UserList;

这样就在前端页面中展示了从后端 API 获取的用户数据。

Mongoose Documentations & Further Readings

MongoDB Documentations: https://docs.mongodb.com

Mongoose Getting Started: http://mongoosejs.com/docs/

Documentations: http://mongoosejs.com/docs/guide.html

Atlas documentation: https://docs.atlas.mongodb.com/import/

相关推荐
间彧4 小时前
ApplicationRunner与CommandLineRunner详解与应用实战
后端
cimeo4 小时前
【C 学习】12.2-函数补充
学习·c#
菠萝吹雪ing4 小时前
GUI 自动化与接口自动化:概念、差异与协同落地
运维·笔记·程序人生·自动化·接口测试·gui测试
聪明的笨猪猪4 小时前
Java Redis “缓存设计”面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试
蓝胖子的多啦A梦4 小时前
低版本Chrome导致弹框无法滚动的解决方案
前端·css·html·chrome浏览器·版本不同造成问题·弹框页面无法滚动
玩代码4 小时前
vue项目安装chromedriver超时解决办法
前端·javascript·vue.js
訾博ZiBo5 小时前
React 状态管理中的循环更新陷阱与解决方案
前端
StarPrayers.5 小时前
旅行商问题(TSP)(2)(heuristics.py)(TSP 的两种贪心启发式算法实现)
前端·人工智能·python·算法·pycharm·启发式算法
微露清风5 小时前
系统性学习C++-第五讲-内存管理
java·c++·学习