明确服务器的职责边界
后端为界面提供一个可靠的工作处理位置。通过 Node.js 和 Express,你将了解路由如何接收请求、执行应用逻辑并返回有用的响应。清晰的边界有助于分离界面呈现、业务规则和数据处理。
让数据持久保存
MongoDB 带来面向文档的数据存储方式。关键在于确定哪些信息应放在一起、记录如何关联应用,以及服务器如何读取或更新它们。设计良好的数据层能让应用在浏览器会话结束后继续发挥作用。
将身份与受保护操作连接起来
身份认证是应用流程的一部分,而不只是一张登录页面。JWT 和 Google OAuth 作用不同:前者代表已认证的会话,后者让用户通过 Google 建立身份。本阶段将路由、数据和身份连接成动态应用。
从概念到可运行的代码
这些代码片段展示了各阶段知识在真实项目中的应用。请将它们作为阅读、分析、修改和测试的起点,而不是不理解就复制的代码。
在服务器边界验证数据
路由从 URL 读取工作坊 ID,并在写入前验证用户输入。无效输入、工作坊不存在和创建成功会返回不同的 HTTP 状态码。
router.post("/workshops/:id/registrations", async (req, res) => {
const { name, email } = req.body;
const workshopId = req.params.id;
if (!name?.trim() || !/^\S+@\S+\.\S+$/.test(email ?? "")) {
return res.status(400).json({ error: "Name and valid email required." });
}
const workshop = await workshops.findOne({ _id: workshopId });
if (!workshop) return res.status(404).json({ error: "Workshop not found." });
const registration = await registrations.insertOne({
workshopId,
name: name.trim(),
email: email.toLowerCase(),
createdAt: new Date(),
});
return res.status(201).json({ id: registration.insertedId });
});通过仓储层隔离数据持久化
仓储层集中管理 MongoDB 操作,并为应用其他部分提供简洁接口。这样路由更容易理解,也能在一个位置替换或测试存储行为。
export function createRegistrationRepository(db) {
const registrations = db.collection("registrations");
return {
async create(input) {
const result = await registrations.insertOne({
workshopId: input.workshopId,
name: input.name.trim(),
email: input.email.toLowerCase(),
status: "pending",
createdAt: new Date(),
});
return { id: result.insertedId.toString(), status: "pending" };
},
findForWorkshop(workshopId) {
return registrations.find({ workshopId }).toArray();
},
};
}阅读后动手修改改变一项要求,先预测结果,再运行代码验证。在评审时,说明你的取舍以及下一步会做的一项改进。