You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 05:45:06