[英]CRUD operations using mongoose and express
我正在使用 mongoose 创建一个快速应用程序,目的是将其连接到前端的 React。
我在下面为客户 controller列出了一些 CRUD 操作,但有一些我不喜欢这种方法的地方。
Customer.findById
时,它会返回null
和 200 响应代码。 如果没有找到客户,我希望它返回 404。 我意识到我可以将catch
响应更改为 404,但我希望有一些通用的错误处理,以防服务器在请求期间出现故障或提供了无效的 ObjectId,这将我带到我的下一个项目。res.status(500).json({error: error.message)
。 我计划连接它以做出反应(我仍在学习)并且我认为 UI 需要向用户显示这些消息?findById
在getCustomerById
、 updateCustomer
和deleteCustomer
中重复。 我觉得这是不好的做法,必须有一个更精简的方法?router.params
的routes
,但我不确定是否应该在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.