我刚开始用 node 实现 redis。在实现身份验证方法期间,我需要检查 token 是否存在于 redis 中,如果不更新 redis 和我的 mongo db 中的新 token ,我需要编写一个大的回调 block 并且无法正确获取结果。我们怎样才能让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);
}
};
最佳答案
不,您将无法同步任何 io 调用,包括 redis 调用。我知道的唯一可用的同步 io 调用是文件系统和控制台。
但是,您可以使用一些编码技术使异步编码更易于管理。
- 先检查错误,尽早返回。
- 将重复的代码移到单独的函数中,例如创建错误结构。
- 使用这个异步库:https://github.com/caolan/async .特别是, waterfall 函数在这里可能很方便。
我还认为您需要将这些函数传入一个回调方法,因为它们是异步的。
- setTokenOnRedis(token);
- deleteTokenOnRedis(token);
我已经重构了您的示例代码,希望它的缩进更少,更易于阅读/维护。我还没有使用异步,我将把它留给你。
就个人而言,我最初发现整个 Node 异步编码模型非常令人沮丧,但你已经习惯了。过了一段时间,你学会了使用各种异步编码模式,然后它就变得几乎可以忍受了:)
一些您可能会觉得有帮助的链接:
- 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);
});
});
});
}
};
关于node.js - 使 Node Redis get() 同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13817221/