NodeJS Express+Mongoose城镇创建逻辑优化:已存在城镇处理问询
Hey there! 你的城镇创建功能能正常运行已经很棒了!不过从代码简洁性、可维护性和框架最佳实践的角度,确实有不少可以优化的地方,我来给你拆解下几个实用的改进方向:
1. 让Mongoose Schema帮你做校验,减少手动判断
你现在手动写了if (!req.body.name)的校验,其实可以把这些规则直接放到Mongoose的Schema里,让框架帮你自动处理,还能顺便搞定重复城镇的判断,不用自己调用findOne:
const townSchema = new mongoose.Schema({ name: { type: String, required: [true, 'Add town name!'], // 必填校验,自定义错误信息 trim: true, // 自动去除首尾空格,避免空字符串或空格串被存入 unique: [true, 'This town already exists!'] // 唯一约束,自动判断重复 } }); const Town = mongoose.model('Town', townSchema);
这样一来,你不用再手动写空值判断和重复查询,Mongoose会在save或create时自动校验,不符合规则就抛出对应错误。
2. 用async/await替代Promise链式调用,提升代码可读性
你的当前代码用了.then()的链式写法,换成async/await能让代码逻辑更线性,嵌套更少,可读性大大提升:
router.post('/create', async (req, res) => { try { // 直接尝试创建城镇,Schema会处理所有校验 await Town.create({ name: req.body.name }); // 创建成功后重定向到城镇列表页(根据你的业务调整) res.redirect('/admin/towns'); } catch (err) { // 处理Mongoose抛出的校验错误 let errors = []; if (err.code === 11000) { // 这是Mongoose唯一约束冲突的错误码,专门处理重复城镇的情况 errors.push({ message: 'This town already exists!' }); } else { // 处理其他校验错误(比如必填项为空) errors = Object.values(err.errors).map(error => ({ message: error.message })); } // 渲染页面并返回错误信息 res.render('admin/towns/index', { errors, name: req.body.name }); } });
3. 提取校验逻辑到中间件(可选,适合多路由复用)
如果你的项目里还有其他和城镇相关的路由(比如编辑)需要类似的输入校验,可以把校验逻辑抽成独立的中间件,让路由代码更干净:
// 定义校验中间件 const validateTownInput = (req, res, next) => { const errors = []; // 这里可以做一些Schema覆盖不到的自定义校验(比如长度限制) if (!req.body.name || req.body.name.trim().length === 0) { errors.push({ message: 'Add town name!' }); } if (req.body.name && req.body.name.length > 50) { errors.push({ message: 'Town name can\'t be longer than 50 characters!' }); } if (errors.length > 0) { return res.render('admin/towns/index', { errors, name: req.body.name }); } // 提前处理输入,避免重复trim req.body.name = req.body.name.trim(); next(); }; // 路由使用中间件 router.post('/create', validateTownInput, async (req, res) => { try { await Town.create({ name: req.body.name }); res.redirect('/admin/towns'); } catch (err) { if (err.code === 11000) { res.render('admin/towns/index', { errors: [{ message: 'This town already exists!' }], name: req.body.name }); } } });
4. 额外小优化:统一错误处理(进阶)
如果你的项目比较大,可以考虑在Express里设置全局错误处理中间件,避免每个路由里重复写错误处理逻辑,不过这个属于进阶优化,适合当项目规模扩大后再考虑。
总的来说,这些优化的核心是利用框架内置能力减少重复代码,同时让逻辑更清晰,后续维护起来也更轻松。
内容的提问来源于stack exchange,提问作者Nenad M
相关产品推荐
相关产品推荐

