所以这是我当前的代码:
/**
* User Registration
* Sends a response object with success true if user was registered.
* Sends a response object with success false if user couldn't be registered.
*/
router.post('/', function(req, res, next) {
var userInfo = req.body;
userInfo.email = sanitize(userInfo.email);
userInfo.password = sanitize(userInfo.password);
if(!validEmail(userInfo.email) || !validPassword(userInfo.password)) { //If the request info is invalid
sendJsonResponse(res, false, error, 400);
}
else {
//Check if e-mail already exists
User.find({email: userInfo.email}, function(err, docs) {
if(err) {
console.log(err);
sendJsonResponse(res, false, "There was an error processing your request.", 400);
}
else if(docs.length > 0) { //If e-mail was found in database, generate error
sendJsonResponse(res, false, "This e-mail already exists, please login or use another e-mail.", 409);
}
else {
//Create user based on data submitted.
var user = new User({email: sanitize(userInfo.email), password: bcrypt.hashSync(sanitize(userInfo.password), 10), permission_level: 'REGULAR'});
//Save it in the database.
user.save(function (err) {
if (err) {
sendJsonResponse(res, false, "There was an error processing your request.", 400);
}
else { //If everything is fine
//Create token to login the registered user
var token = jwt.sign(user, config.secret, {
expiresIn: '24h' // expires in 24 hours
});
sendJsonResponse(res, true, "You have been registered!", 200, token);
}
});
}
});
}
error = "";
});
此代码用于用户注册。我正在使用我编写的函数 (validEmail/validPassord) 来验证发送到我的 REST API 的电子邮件和密码。
还有 sendJsonResponse,它发送带有特定错误和错误代码的响应。
我觉得我做的还不错,但我还是觉得这里还有改进的空间。我特别不喜欢所有的 if/else。我可以在这里做些什么来提高最佳实践/代码质量吗?
最佳答案
如果我们只查看您的代码,那很好(逻辑、错误处理、格式化您的响应的功能......)。
但是查看您的代码,我假设您使用的是 Express
微框架来创建你的后端服务(API?),所以关于你的 API 的设计和你使用 Express 的方式有一些需要改进的地方......
将数据库与路由分开
对您的数据库的一个请求可能会导致不同的错误(重复键、一些约束、错误值......)并服务于不同的 perpices。所以最好创建模块来处理与数据库的交互,这样错误处理会更干净,代码更可重用。
例子 :
创建模块userModel
这将包含多种方法来处理数据库中的用户。
考虑 getBy
允许您通过“键”(getBy({name: 'Doe', age: 25})
)过滤用户的方法。
这个方法可以被不同的路由使用并返回不同类型的错误,所以最好把它写在一个模块里面。
它将减少代码重复,使代码更具可读性并帮助您改进错误处理。
快速路由器
我看到您正在使用 Express 路由器 ( router.post('/', ... )
)。
由于您正在设计一个 REST API,您的方法 GET、POST、PUT 和 DELETE 将共享相同的路由名称。
Express 路由器允许您使用以下语法来执行此操作:
router.route('/routeName')
.get(...)
.post(...)
.put(...)
.delete(...);
这不是什么大问题,但它使代码更好,并迫使您尊重 REST 架构约束。 Express 中间件
我看到您正在使用函数来验证您的请求正文并格式化您的回复。这通常由中间件管理。
中间件是 Express(带有路由器)最重要的功能之一。它们是具有以下“签名”的函数:`function(req, res, next){}`,可以链接。
每个中间件可以:
req
参数)res
提供的方法发送响应参数(例如:res.status(200).json({created: true})
)next()
因此,中间件允许您使用一个简单的函数列表来构建程序的逻辑,这些函数将一个接一个地调用。
例子 :
[check req.body](1) --> [write user in the DB](2) --> [format response](3)
中间件真是太棒了,它会让你写出更好、更干净、设计良好的 API :) 异步/等待
我们都讨厌回调 hell ,这是事实,这就是为什么我们通常使用像
Promise
这样的东西。 .但即使是 Promise 有时也会很痛苦,所以我们有 async/await
这让事情变得更简单:它允许您以与编写同步代码相同的方式编写异步代码!
一些代码来说明以上几点
|___models/
| |___users.js
|
|___controllers/
| |___users.js
|
|___routes/
| |___register.js
|
|___middlewares/
|___validation.js
// models/users.js
import db from 'dbModule';
const save = async (userObj) => {
const testUserMail = await db.users.find({email: userObj.email});
if (testUserMail.length > 0)
return {success: false, err: "The email already exists"};
await db.users.save(userObj);
const savedUser = await db.users.findById(userObj.id);
return {success: true, user: savedUser};
}
exports default {save};
// controllers/users.js
import userModel from '../models/users';
const register = (req, res, next) => {
console.log(req.example); // "hey I'm here"
const dbReq = await userModel.save(req.body);
if (dbReq.err && !dbReq.success)
return res.status(400).json({success: false, data: dbReq, message: "failed !"})
const registeredUser = dbReq.user;
res.json({success: true, data: {user: registeredUser}, message: "User is registered !");
}
export default {register};
// middlewares/validation.js
const checkUser = (req, res, next) => {
req.example = "hey I'm here";
if (isOk(req.body.email) && isOk(req.body.password))
return next();
else
return res.status(400).json({success: false, data: null, message: "failed: bad request body"}))
}
export default {checkUser};
// routes/register.js
import express from 'express';
import validation from '../middlewares/validation';
import userCtrl from '../controllers';
const router = express.Router();
router.route('/')
.post(validation.checkUser, userCtrl.register)
快速而持久 (我发誓)解释:
userCtrl.register
)。 req
通过之前的中间件进行的修改(这里,我们将 example
键添加到 req
对象)。 await
用于) async
将用户保存在数据库中函数 --> 避免回调 hell 希望对您有所帮助,阅读时间不会太长,
最好的祝福,
关于javascript - 如何改进 Node.js 中的数据验证? (寻找最佳实践),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43022885/