Node.js待办项目如何正确将Model层代码拆分到独立文件
拆分Model层的正确实现方案
首先将所有和todo数据读写、业务操作相关的逻辑单独抽离到独立的Model文件,和Controller层的请求处理逻辑完全解耦即可,完整实现如下:
第一步:新建todo.model.js文件(Model层)
存放所有数据读写、todo实体操作逻辑:
const fs = require('fs/promises'); const path = require('path'); const { v4: uuidv4 } = require('uuid'); // 统一拼接data.json绝对路径,避免不同执行目录下相对路径失效 const DATA_PATH = path.join(__dirname, '../../data/data.json'); class TodoModel { // 读取所有todo数据 static async getAllTodos() { const data = await fs.readFile(DATA_PATH, 'utf-8'); return JSON.parse(data); } // 保存todo列表到本地文件 static async saveTodos(todos) { await fs.writeFile(DATA_PATH, JSON.stringify(todos, null, 2), 'utf-8'); } // 新增todo项 static async createTodo(todoData) { const todos = await this.getAllTodos(); const newTodo = { id: uuidv4(), title: todoData.title, description: todoData.description, dateOfCreate: new Date(), lastModified: new Date(), check: false }; todos.push(newTodo); await this.saveTodos(todos); return newTodo; } } module.exports = TodoModel;
第二步:改写todo.controller.js(Controller层)
仅保留请求体接收、参数校验、响应返回逻辑,数据操作全部调用Model层方法:
const TodoModel = require('../models/todo.model'); class TodoController { async createTodo(req, res) { // 流式接收请求体 const buffers = []; for await (const chunk of req) { buffers.push(chunk); } try { const todoData = JSON.parse(Buffer.concat(buffers).toString()); // 校验必填参数 if (!todoData.title || !todoData.description) { res.writeHead(400, { 'Content-Type': 'application/json' }); return res.end(JSON.stringify({ msg: '标题和描述不能为空' })); } const newTodo = await TodoModel.createTodo(todoData); res.writeHead(201, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(newTodo)); } catch (err) { res.writeHead(500, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ msg: '创建失败', error: err.message })); } } } // 导出实例化后的控制器,避免路由层重复实例化 module.exports = new TodoController();
第三步:修正todo.router.js逻辑
原有代码直接调用类而非实例会报错,修正后代码如下:
const url = require("url"); const todoController = require("../controllers/todo.controller"); const todoRouter = (req, res) => { const urlparse = url.parse(req.url, true); if (urlparse.pathname == "/todos" && req.method == "POST") { todoController.createTodo(req, res); } }; module.exports = todoRouter;
原有代码问题说明
- 定义的Controller是类,没有实例化就直接调用方法会抛出异常
- 原有参数校验
if ((title, description))写法错误,逗号运算符只会返回最后一个值,会漏掉title的非空校验 - 写文件回调中
if (err) throw error变量名拼写错误,err写成了error会抛出未定义异常 - 没有给请求返回响应,客户端会一直处于等待超时状态
内容的提问来源于stack exchange,提问作者tan4ok
相关产品推荐
相关产品推荐

