javascript - 我怎样才能更好地优化这些数据库查询/功能流程?

标签 javascript node.js optimization mongoose lodash

我已经从游戏开发转向编写支持后端。到目前为止,一切似乎都很顺利,但是当我开始编写一个 friend 系统时,我遇到了这个对我来说似乎很脏的函数流程。而且我敢肯定,我现在只是在拼凑它。任何 node.js 向导会告诉我如何改进它吗?

相当确定我也应该在 Redis 中缓存播放器查找。

acceptfriend: function(req, res){
    //Find our user
    User.findById( req.decoded._id, function(err, user){
        //error occured
        if(err){
            return res.status(401).send(err);
        }
        //no user found
        if(!user){
            return res.status(401).json({
                succes: false,
                message: 'no user found with that id'
            } );
        }
        //Does the request exist?
        if( !_.any( user.social.friendRequests, {id: req.params.id} ) ){
            return res.status(401).json( {
                succes: false,
                message: 'friend request not found'
            } );
        }
        //find the user that belongs to the request
        User.findById( req.params.id, function(err, friend){
            //error occured
            if(err){
                return res.send(err);
            }
            //user doesnt exist
            if(!friend){
                return res.status(401).json({
                    succes: false,
                    message: 'no user found with that id'
                } );
            }
            //Pull the request from the friendRequests array
            user.social.friendRequests.pull( req.params.id );
            //Add the friend
            user.social.friends.addToSet( {
                user_id: friend._id,
                name: friend.username,
                corp: 'n/a'
            } );
            //Add the user to the friends list as well
            friend.social.friends.addToSet({
                user_id: user._id,
                name: user.username,
                corp: 'n/a'
            });
            //save the docs
            user.save();
            friend.save();
        } );
        //return success
        return res.status(200).json({
            success: true,
            message: 'friend succesfully added'
        });
    } );
}

最佳答案

1- 首先,你有一个很大的功能。你必须把它分成一些功能。这样做,您就有可能使用任何测试框架对其进行测试。

2- 将错误响应的句柄委托(delegate)给 Controller 。

from -> return res.status(401).send(err);
to (with Promises)-> deferred.reject(err); 
to (normal way)   -> throw new Error(err); 

3- 您可以使用 Promises 来管理 Node 的异步行为以清除代码。 我创建了一个示例,也许第一次无法正常工作,请随时修复不正确的引用。 User ref,'acceptfriend' 方法...

要点:https://gist.github.com/aitoraznar/b7099ad88ead0cdab256

var Promise = require('bluebird');
var _ = require('lodash');
//var User = app.models.User;

var ERRORS = {
    userNotFoundError: {
        code: 401,
        success: false,
        message: 'no user found with that id'
    },
    friendRequestNotFoundError: {
        code: 401,
        success: false,
        message: 'friend request not found'
    },
    friendNotFoundError: {
        code: 401,
        success: false,
        message: 'no friend found with that id'
    }

}

var SUCCESS_MESSAGES= {
    friendAddedSuccessfully: {
        success: true,
        message: 'friend succesfully added'
    }
};

var userDAO = {
    /*
     *
     */
    getUserById: function(id) {
        var deferred = Promise.pending();

        User.findById(id, function(err, user) {
            //error occured
            if (err) {
                err.code = 401;
                return deferred.reject(err);
            }

            //no user found
            if (!user) {
                return deferred.reject(ERRORS.userNotFoundError);
            }

            deferred.resolve(user);
        });

        return deferred.promise;
    },

    /*
     * Does the request exist?
     */
    checkFriendRequest: function(user, friendId) {
        var deferred = Promise.pending();

        if (userDAO.haveFriendRequestFrom(user, friendId)) {
            deferred.resolve(user, friendId);
        } else {
            return deferred.reject(ERRORS.friendRequestNotFoundError);
        }

        return deferred.promise;
    },

    /*
     * 
     */
    haveFriendRequestFrom: function(user, friendId) {
        return _.any(user.social.friendRequests, {id: friendId });
    },

    /*
     * 
     */
    getFriend: function(user, friendId) {
        var deferred = Promise.pending();

        userDAO.getUserById(friendId)
            .then(function(friend) {
                deferred.resolve(user, friend);
            }, 
            function(error) {
                if (error === ERRORS.userNotFoundError) {
                    // Then the error is friend not found
                    // Override the error
                    error = ERRORS.friendNotFoundError;
                }

                return deferred.reject(error);
            });

        return deferred.promise;
    },

    /*
     * 
     */
    makeFriendship: function(user, friend) {
        var deferred = Promise.pending();

        //Pull the request from the friendRequests array
        user.social.friendRequests.pull(friend._id);

        //Add the friend
        user.social.friends.addToSet( {
            user_id: friend._id,
            name: friend.username,
            corp: 'n/a'
        } );
        //Add the user to the friends list as well
        friend.social.friends.addToSet({
            user_id: user._id,
            name: user.username,
            corp: 'n/a'
        });
        //save the docs
        user.save();
        friend.save();

        // Return the new friendship
        var friendship = {
            user: user,
            friend:friend
        };
        
        deferred.resolve(friendship);

        return deferred.promise;
    },

    /*
     *
     */
    friendRequestError: function(err) {
        var deferred = Promise.pending();

        // Propagate de error
        deferred.reject(err);

        return deferred.promise;
    },

    /*
     *
     */
    friendRequest: function(userId, friendId) {
        var deferred = Promise.pending();

        // Get user by ID
        userDAO.getUserById(userId)
            
            // Check if the user is able to add the friend
            .then(userDAO.checkFriendRequest, userDAO.friendRequestError)

            // Get the friend to add
            .then(userDAO.getFriend, userDAO.friendRequestError)

            // Make the friendship
            .then(userDAO.makeFriendship, userDAO.friendRequestError)

            // Response to the controller
            .then(
                function(friendship) {
                    // Resolve with new friendship
                    // This goes to 'success' function in controller
                    deferred.resolve(friendship);
                }, function(error) {
                    // This goes to 'error' function in controller
                    deferred.reject(error);
                })

        return deferred.promise;
    }
};


// Controller
var acceptfriend = function(req, res, next) {
    var userId = req.decoded._id;
    var friendId = req.params.id;

    userDAO.friendRequest(userId, friendId)
        .then(function(friendRequest) {
            console.log('---> SUCCESS');
            
            //return success
            return res.status(200)
                .json(SUCCESS_MESSAGES.friendAddedSuccessfully);
        }, function(error) {
            console.error('---> ERROR', error);

            return res.status(error.code).json(error);
        });
}

4- 在集合/表中创建数据库索引

问候, 艾特

关于javascript - 我怎样才能更好地优化这些数据库查询/功能流程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33734223/

相关文章:

javascript - SyntaxError : Unexpected token u at Object. 为 JSON.parse() 解析( native )NodeJS

javascript - 在 Node 中处理嵌套异步等待调用的正确方法是什么?

python - 如何优化以下Python函数以使其执行速度更快?

python - 使用 numpy.meshgrid 定义二次函数

javascript - 使用 box-sizing :border-box 时,jQuery.height() 在 WebKit 和 Firefox 中的行为不同

javascript - Bootstrap 3 - 下拉菜单项中的取消按钮

javascript - javascript/NodeJS 中的变量范围问题

performance - 更符合人类逻辑的源代码是否会产生更优化的编译代码?

javascript - 如何知道浏览器空闲时间?

javascript - 如何在 jquery 上合计两个不同的下拉选项