Web 开发 27
1 路由router引入语法解释
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)
- 将查询结果发送给客户端
执行流程
- 路由匹配:收到 GET 请求到
/stories
- 数据库查询:执行
Story.find({})
查找所有故事 - 异步处理:等待数据库查询完成(Promise)
- 结果处理:查询完成后执行
.then()
回调 - 响应发送:使用
res.send()
将数据返回客户端
等价的传统写法
// 使用 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
方法处理请求成功后的回调,将获取到的评论数据comments
用setComments
方法设置到组件的状态中,以便在组件中渲染评论。
后端如何获取参数
在后端(通常是基于 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 */
的地方,替换成查询逻辑。
- 方法一(使用对象查询):
Comment.find({ parent: req.query.parent }).then(comments => {// 处理查询到的评论数据,比如返回给前端res.json(comments);}).catch(err => {// 处理错误res.status(500).json({ error: err.message });});
- 方法二(使用
where
方法):
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
模型。然后编写路由:
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
函数构建了一个包含 parent
和 content
字段的对象 body
,并通过 post
方法将其发送到 /api/comment
接口 。其中,parent
表示父级内容的标识(比如文章 ID 等),content
是评论的具体内容,value
就是用户输入的评论文字。
白色小窗里显示了实际发送的请求负载示例 {parent: 0, content: "I don't :("}
,可以看到具体的 parent
值为 0
,content
值为 "I don't :("
,这是在模拟实际发送请求时携带的数据结构和数据内容。
在后端开发中,了解请求负载的结构非常重要,这样才能正确地解析和处理前端发送过来的数据,比如将评论内容存储到数据库对应的字段中,或者基于 parent
字段进行关联查询等操作 。
【怎么在vscode里面查看这个白色窗口的】
在 VSCode 中本身没有直接查看请求负载(Request Payload)这样的可视化窗口,不过你可以通过以下几种方式间接获取类似信息:
借助浏览器开发者工具
- 打开开发者工具:在 Chrome、Firefox 等主流浏览器中,按下
F12
键或者通过菜单找到 “开发者工具” 选项打开它。 - 切换到 Network 面板:在开发者工具界面中,点击
Network
(网络)选项卡。 - 触发 POST 请求:在你的网页应用中执行触发 POST 请求的操作,比如点击提交评论按钮等。
- 查看请求详情:在
Network
面板中找到对应的 POST 请求,点击它,然后在右侧展开的详情中找到Payload
或者Request Body
部分,就能看到发送的请求负载内容了。
使用 VSCode 插件(以 REST Client 插件为例)
- 安装插件:在 VSCode 左侧的插件市场中,搜索
REST Client
插件,然后点击安装并重启 VSCode 让插件生效。 - 创建请求文件:在 VSCode 中新建一个文件,后缀名可以设为
.http
或者.rest
,比如comments.http
。 - 编写请求内容:按照 REST Client 插件的语法格式编写 POST 请求,示例如下:
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/json
、application/x-www-form-urlencoded
等。
4. 发送请求并查看:点击请求代码块旁边的 Send Request
按钮发送请求,在下方的 Response
区域就能看到请求的响应结果,同时在请求发送时,你可以通过浏览器开发者工具或者后端日志等方式确认请求负载内容。
查看后端日志
如果是在后端接收和处理这个 POST 请求,你可以在后端代码中添加日志输出,以 Node.js + Express 为例:
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 库的话,连接代码大致如下:
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 模型查询数据库,然后将结果返回给前端。代码示例:
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
接口:
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/