javascript - 如何改进 Node.js 中的数据验证? (寻找最佳实践)

标签 javascript node.js

所以这是我当前的代码:

/**
 * 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)
    

    快速而持久 (我发誓)解释:
  • 首先我们检查我们的 body (如果我们愿意,我们可以修改它)。如果出现问题,我们发送 400 Bad request Response,否则,我们调用 next 并转到下一个中​​间件 (userCtrl.register)。
  • 我们检索到 req通过之前的中间件进行的修改(这里,我们将 example 键添加到 req 对象)。
  • 我们通过调用 ( = await 用于) async 将用户保存在数据库中函数 --> 避免回调 hell
  • 就是这样,我们保存用户并发送 200 响应。

  • 希望对您有所帮助,阅读时间不会太长,
    最好的祝福,

    关于javascript - 如何改进 Node.js 中的数据验证? (寻找最佳实践),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43022885/

    相关文章:

    javascript - 针对原生 js 的 angular json 相关函数

    javascript - 我怎样才能禁用事件监听器?或者有一个停止按钮来实现它的功能?

    node.js - 带有参数的 Axios Node.Js GET 请求未定义

    javascript - 如何将自定义数据传递给我的 Mocha 测试?

    javascript - 如何使用 Promise.all() 和异步循环?

    javascript - 如何在 ie8 中设置包含函数值的 OnClick 属性?

    javascript - 如何强制 javascript 类忽略输出中外部添加的字段

    javascript - 在node js中的函数外部访问时变量的值变为空

    json - 使用 JSON 和 TypeScript 进行静态类型化

    javascript - 无法检查一个正方形是否为空 tictactoe 游戏 jquery