使节点 Redis get() 同步
Posted
技术标签:
【中文标题】使节点 Redis get() 同步【英文标题】:Make Node Redis get() Synchronous 【发布时间】: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);
;
【问题讨论】:
【参考方案1】:不,您将无法同步任何 io 调用,包括 redis 调用。我知道的唯一可用的同步 io 调用是文件系统和控制台。
但是,您可以使用一些编码技术使异步编码更易于管理。
先检查错误,提前返回。 将重复代码移动到单独的函数中,例如创建错误结构。 使用这个异步库:https://github.com/caolan/async。特别是,瀑布函数在这里可能很方便。我还认为您需要将这些函数传入一个回调方法,因为它们是异步的。
setTokenOnRedis(token); deleteTokenOnRedis(token);我已经重构了您的示例代码,希望它的缩进更少,更易于阅读/维护。我没有使用异步,我将把它留给你。
就个人而言,我最初发现整个节点异步编码模型非常令人沮丧,但你已经习惯了。过了一段时间,你学会了使用各种异步编码模式,然后就可以忍受了:)
一些您可能会觉得有帮助的链接:
error handling in asynchronous node.js calls Node.js Best Practice Exception Handling How to avoid long nesting of asynchronous functions in Node.js重构代码:
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 客户端更加同步,但它是对注册回调函数的(小)改进,使您的代码更具可读性。
【讨论】:
以上是关于使节点 Redis get() 同步的主要内容,如果未能解决你的问题,请参考以下文章