繁体   English   中英

使用 mongoose 和 express 的 CRUD 操作

[英]CRUD operations using mongoose and express

我正在使用 mongoose 创建一个快速应用程序,目的是将其连接到前端的 React。

我在下面为客户 controller列出了一些 CRUD 操作,但有一些我不喜欢这种方法的地方。

  1. 当使用带有未找到的有效 ObjectID 的Customer.findById时,它会返回null和 200 响应代码。 如果没有找到客户,我希望它返回 404。 我意识到我可以将catch响应更改为 404,但我希望有一些通用的错误处理,以防服务器在请求期间出现故障或提供了无效的 ObjectId,这将我带到我的下一个项目。
  2. 如果我提供了无效的 ObjectId,我想提供一些有意义的消息,500 是正确的响应代码吗?
  3. 错误处理:我是否以正确的方式返回错误? 当前错误返回带有错误消息的字符串。 我应该返回 JSON 吗? 例如res.status(500).json({error: error.message) 我计划连接它以做出反应(我仍在学习)并且我认为 UI 需要向用户显示这些消息?
  4. findByIdgetCustomerByIdupdateCustomerdeleteCustomer中重复。 我觉得这是不好的做法,必须有一个更精简的方法?
  5. 我想要一个 function 来验证 ObjectId 是否有效。 我知道我可以做到这一点是使用router.paramsroutes ,但我不确定是否应该在routes文件中检查有效的 id,因为它看起来像是controller应该处理的东西? 请参阅下面我做的另一个项目的路线示例。

基于上述内容,改进我的代码的最佳实践和建议方法是什么? 我已经阅读了 mongoose、mozilla 和 stackoverflow Q&A 的文档,但它们似乎没有解决这些问题(至少我找不到)。

我真的经过一些指导或验证,我所做的事情是正确还是错误。

客户.controller.js

const Customer = require("../models/customer.model");

exports.getCustomers = async (req, res) => {
  try {
    const customers = await Customer.find();
    res.status(200).json(customers);
  } catch (error) {
    res.status(500).send(error.message);
  }
};

exports.getCustomerById = async (req, res) => {
  try {
    const customer = await Customer.findById(req.params.id);
    res.status(200).json(customer);
  } catch (error) {
    res.status(500).send(error.message);
  }
};

exports.addCustomer = async (req, res) => {
  try {
    const customer = new Customer(req.body);
    await customer.save().then(res.status(201).json(customer));
  } catch (error) {
    res.status(500).send(error.message);
  }
};

exports.updateCustomer = async (req, res) => {
  try {
    const customer = await Customer.findById(req.params.id);
    Object.assign(customer, req.body);
    customer.save();
    res.status(200).json(customer);
  } catch (error) {
    res.status(500).send(error.message);
  }
};

exports.deleteCustomer = async (req, res) => {
  try {
    const customer = await Customer.findById(req.params.id);
    await customer.remove();
    res.status(200).json(customer);
  } catch (error) {
    res.status(500).send(error.message);
  }
};

Router.params 示例这是一个路由文件(与我当前的应用程序无关),并作为我过去如何使用router.params的示例提供。

const express = require("express");
const router = express.Router();
const mongoose = require("mongoose");
const Artist = require("../models/Artist");
const loginRequired = require("../middleware/loginRequired");

const {
  getArtists,
  addArtist,
  getArtistById,
  updateArtist,
  deleteArtist,
} = require("../controllers/artistController");

router
  .route("/")
  .get(loginRequired, getArtists) // Get all artists
  .post(loginRequired, addArtist); // Create a new artist

router
  .route("/:id")
  .get(loginRequired, getArtistById) // Get an artist by their id
  .put(loginRequired, updateArtist) // Update an artist by their id
  .delete(loginRequired, deleteArtist); // Delete an artist by their id

router.param("id", async (req, res, next, id) => {
  // Check if the id is a valid Object Id
  if (mongoose.isValidObjectId(id)) {
    // Check to see if artist with valid id exists
    const artist = await Artist.findOne({ _id: id });
    if (!artist) res.status(400).json({ errors: "Artist not found" });

    res.locals.artist = artist;
    res.locals.artistId = id;

    next();
  } else {
    res.status(400).json({ errors: "not a valid object Id" });
  }
});

module.exports = router;

我个人喜欢让错误处理更加全球化,所以我会写一些类似的东西

constPrettyError = require('pretty-error')
const pe = new PrettyError()

const errorHandler = (err, req, res, next) => {
    if (process.env.NODE_ENV !== 'test') {
        console.log(pe.render(err))
    }
    return res
        .status(err.status || 500)
        .json({ error: { message: err.message || 'oops something went wrong' } })
}

module.exports = errorHandler

作为处理程序

在您的索引/服务器文件中

app.use(errorHandler)

然后在你的处理程序中

  } catch (err) {
    next(err);
  }

举个例子

 if (!artist) next({ message: "Artist not found" ,status:404 });

另外,请注意,您可以自定义此错误处理程序以根据需要切换每个状态的自定义错误(或对象)

const errorHandler = (err, req, res, next) => {
    if (process.env.NODE_ENV !== 'test') {
        console.log(pe.render(err))
    }
    const messagePerStatus = {
        404: 'not found',
        401: 'no authorization'
    }
    const message = messagePerStatus[err.status]
    return res
        .status(err.status || 500)
        .json({
            error: { message: message || err.message || 'oops something went wrong' }
        })
}

那么就

 if (!artist) next({status:404 });

我也同意 Asaf Strilitz 的回答,但仍然需要展示我在项目中所做的事情

创建自定义错误 class

应用错误.js

class AppError extends Error {
  constructor(statusCode, message) {
    super();
    // super(message);
    this.statusCode = statusCode || 500 ;
    this.message = message || "Error Something went wrong";
  }
}

module.exports = AppError;

创建错误处理中间件

错误.js

const AppError = require("../helpers/appError");

const errors = (err, req, res, next) => {
    // console.log(err);
  
    let error = { ...err };

    error.statusCode = error.statusCode;
    error.message = error.message;

    res.status(error.statusCode).json({
      statusCode: err.statusCode,
      message: err.message,
    });
  };
  
  exports.errors = errors;

创建一个中间件来验证 object id

validateObjectId.js

const mongoose = require("mongoose");
const AppError = require("appError");

module.exports = function (req, res, next) {
  const { _id } = req.params;
  if (_id && !mongoose.Types.ObjectId.isValid(_id)) {
    throw new AppError(422, "Invalid ID field in params");
  }
  next();
};

在你的 app.js

const { errors } = require("errors");


// At the end of all middlewares

// Error Handler Middleware
app.use(errors);

在您的路线文件中

const express = require("express");
const router = express.Router();
const mongoose = require("mongoose");
const Artist = require("../models/Artist");
const loginRequired = require("../middleware/loginRequired");
const validateId = require("validateObjectId");

const {
  getArtists,
  addArtist,
  getArtistById,
  updateArtist,
  deleteArtist,
} = require("../controllers/artistController");

// Your routes
router
  .route("/:id")
  .get(validateId, loginRequired, getArtistById) // Get an artist by their id
  .put(validateId, loginRequired, updateArtist) // Update an artist by their id
  .delete(validateId, loginRequired, deleteArtist); // Delete an artist by their id


module.exports = router;

现在关于重复 findById 方法,我没有看到任何不好的地方,因为它特定于数据库调用,您仍然可以在 model 本身上引入一个静态方法,或者在 cntroller 上创建一个方法,但仍然需要检查它是否返回找到的 object并处理错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM