【问题标题】:Make Node Redis get() Synchronous使节点 Redis get() 同步
【发布时间】:2012-11-28 19:50:35
【问题描述】:

我刚刚开始使用 node 实现 redis。在实现身份验证方法期间,我需要检查令牌是否存在于 redis 中,如果不更新 redis 和我的 mongo db 中的新令牌,我需要编写一个大的回调块并且无法正确获取结果。我们怎样才能让 redis 得到回调的红色。我们怎样才能使它同步。示例代码如下。

module.exports.authenticate = function(request, response)   {
    var reply = {};

    if(UserSchema)  {
        var UserModel, attributes;

        /** Registering User Model; **/
        mongoose.model('user', UserSchema);
        UserModel = mongoose.model('user');

        attributes = request.params;

        UserModel.findOne(attributes, "_id name email token", function(error, user) {

            if(!error && user)  {
                var token;

                //delete user.password;
                token = user.token;

                /** Checking token exists in redis; **/
                redisClient.get(token, function(error, value)   {
                    if(value === null && error === null)    {

                        /** Creating new token; **/
                        token = require('crypto').createHash('md5').update("" + (new Date()).getTime()).digest("hex");
                        user.token = token;

                        /** Storing new token on redis; **/
                        setTokenOnRedis(token);

                        /** Updating token in the user model; **/
                        UserModel.update({ _id : user._id}, { token : token }, function(error, user)    {
                            if(error !== null && user === null) {
                                deleteTokenOnRedis(token);

                                /** Error message; **/
                                reply = {
                                    error : true,
                                    code : "AUTH#001",
                                    msg : "User authentication failed, Please check user credentials."
                                }
                                response.send(reply);

                            }else if(error === null && user !== null)   {
                                reply = user;
                                response.send(reply);
                            }
                        });
                    }else if(value !== null)    {
                        reply = user;
                        response.send(reply);
                    }else   {
                        /** Error message; **/
                        reply = {
                            error : true,
                            code : "AUTH#001",
                            msg : "User authentication failed, Please check user credentials."
                        };
                        response.send(reply);
                    }
                });
            }else   {
                /** Error message; **/
                reply = {
                    error : true,
                    code : "AUTH#001",
                    msg : "User authentication failed, Please check user credentials."
                }
            }       
        });
    }else   {

        /** Error message; **/
        reply = {
            error : true,
            code : "AUTH#001",
            msg : "User authentication failed, Please check user credentials."
        }

        response.send(reply);
    }
};

【问题讨论】:

    标签: node.js redis node-redis


    【解决方案1】:

    不,您将无法同步任何 io 调用,包括 redis 调用。我知道的唯一可用的同步 io 调用是文件系统和控制台。

    但是,您可以使用一些编码技术使异步编码更易于管理。

    • 先检查错误,提前返回。
    • 将重复代码移动到单独的函数中,例如创建错误结构。
    • 使用这个异步库:https://github.com/caolan/async。特别是,瀑布函数在这里可能很方便。

    我还认为您需要将这些函数传入一个回调方法,因为它们是异步的。

    • setTokenOnRedis(token);
    • deleteTokenOnRedis(token);

    我已经重构了您的示例代码,希望它的缩进更少,更易于阅读/维护。我没有使用异步,我将把它留给你。

    就个人而言,我最初发现整个节点异步编码模型非常令人沮丧,但你已经习惯了。过了一段时间,你学会了使用各种异步编码模式,然后就可以忍受了:)

    一些您可能会觉得有帮助的链接:

    重构代码:

    module.exports.authenticate = function(request, response){
      authenticate(request, response, function(err, reply){
        if(err){
           reply = authenticationError(err);
        }
        response.send(reply);
      });
    };
    
    var authenticationError = function(internalmsg){
      return {
        internalmsg : internalmsg,
        error : true,
        code : "AUTH#001",
        msg : "User authentication failed, Please check user credentials."
      };
    };
    
    var authenticate = function(request, response, callback)   {
      if(UserSchema)  {
        var UserModel, attributes;
    
        /** Registering User Model; **/
        mongoose.model('user', UserSchema);
        UserModel = mongoose.model('user');
    
        attributes = request.params;
    
        UserModel.findOne(attributes, "_id name email token", function(err, user) {
          if(err || !user){
            return callback(err || "UserModel.findOne, no user");
          }
    
          var token;
    
          //delete user.password;
          token = user.token;
    
          /** Checking token exists in redis; **/
          redisClient.get(token, function(err, value){
            if(err){
              return callback(err);
            }
            if(value){
              return callback(null, value);
            }
    
            /** Creating new token; **/
            token = require('crypto').createHash('md5').update("" + (new Date()).getTime()).digest("hex");
            user.token = token;
    
            /** Storing new token on redis; **/
            setTokenOnRedis(token);
    
            /** Updating token in the user model; **/
            UserModel.update({ _id : user._id}, { token : token }, function(err, user) {
              if(err || !user) {
                deleteTokenOnRedis(token);
                return callback(err || "UserModel.update, no user found");
              }
              callback(null, user);
            });
          });
        });
      }
    };
    

    【讨论】:

    • 感谢您的折射代码。您绘制的点正是我正在寻找的。​​span>
    【解决方案2】:

    在最初的问题发生多年后,Node.js 的 Redis 客户端本质上仍然是异步的 - 并且不太可能改变。

    但为了更方便地处理这种工作方式,该包支持承诺,如http://redis.js.org/#redis-a-nodejs-redis-client-usage-example-promises 所述。

    它不会使 Node.js 和 Redis 客户端更加同步,但它是对注册回调函数的(小)改进,使您的代码更具可读性。

    【讨论】:

      猜你喜欢
      • 2023-03-22
      • 2021-11-01
      • 1970-01-01
      • 2019-08-18
      • 2017-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-09-27
      相关资源
      最近更新 更多