我不得不采取以下函数来评估密码是否在用户的密码历史记录中。下面是代码:Node.js For循环内部异步回调
isPasswordInPwdHistory : function(redisClient, userId, encPassword, cb) {
var key = 'user:' + userId + ':pwdhistory';
redisClient.llen(key, function(err, reply) {
if (err) {
status.results = [ ];
xutils.addStatusResultsItem(status.results, err, null, null, null);
cb(status);
}
else {
var numPwds = reply;
var match = false;
var funcError;
for (i=0; i <= numPwds - 1; i++) {
var error;
var pwdValue;
redisClient.lindex(key, i, function(err, reply) {
if (err) {
console.log('lindex err = ' + err);
error = err;
}
else {
console.log('lindex reply = ' + reply);
console.log('lindex encPassword = ' + encPassword);
console.log('lindex (encPassword === reply) = ' + (encPassword === reply));
pwdValue = reply;
}
});
console.log('for-loop error = ' + error);
console.log('for-loop pwdValue = ' + pwdValue);
console.log('for-loop (encPassword === pwdValue) = ' + (encPassword === pwdValue));
if (error) {
funcError = error;
break;
}
else if (encPassword === pwdValue) {
console.log('passwords match');
match = true;
break;
}
}
console.log('funcError = ' + funcError);
console.log('match = ' + match);
if (funcError) {
status.results = [ ];
xutils.addStatusResultsItem(status.results, err, null, null, null);
cb(status);
}
else
cb(match);
}
});
}
这里是控制台输出:
for-loop error = undefined
for-loop pwdValue = undefined
for-loop (encPassword === pwdValue) = false
funcError = undefined
match = false
isPasswordInPwdHistory = false
lindex reply = 5f4f68ed57af9cb064217e7c28124d9b
lindex encPassword = 5f4f68ed57af9cb064217e7c28124d9b
lindex (encPassword === reply) = true
一旦我离开redisClient.lindex的范围()调用我失去了价值。我如何在for循环中将这些值传递给评估?
UPDATE
我重构一下代码索引i发出的redisClient.lindex()回调时来处理新的密码(encPassword)与现有密码的匹配。
isPasswordInPwdHistory : function(redisClient, userId, encPassword, cb) {
var status = new Object();
var key = 'user:' + userId + ':pwdhistory';
redisClient.llen(key, function(err, reply) {
if (err) {
status.results = [ ];
xutils.addStatusResultsItem(status.results, err, null, null, null);
cb(status);
}
else {
var numPwds = reply;
var loopCt = 0;
for (i=0; i <= numPwds - 1; i++) {
loopCt++;
redisClient.lindex(key, i, function(err, reply) {
if (err) {
status.results = [ ];
xutils.addStatusResultsItem(status.results, err, null, null, null);
cb(status);
}
else if (encPassword === reply) {
status.results = [ ];
xutils.addStatusResultsItem(status.results, null, 0, null, true);
cb(status);
}
else if (loopCt === numPwds && encPassword !== reply) {
status.results = [ ];
xutils.addStatusResultsItem(status.results, null, 0, null, false);
cb(status);
}
});
}
}
});
}
不幸的是,调用者看到状态===未定义,即使encPassword ===回复为真,我发出cb(状态)。如何在发出cb(状态)后退出for-loop?
布兰登,谢谢你的反馈!我一定会检查异步库。至于使用Redis列表数据类型:我只关心存储最后5个密码。在将新项目添加到此列表中并超过5个元素后,我将列表重新分配回5个元素。实际上,我不需要设置/排序集的额外内存开销。但是,你指出这点非常敏锐。最适合你的家伙! – Chris
我在redisClient.lindex()下添加了一个回调函数。 – Chris
克里斯,编辑(你应该把你的问题编辑)将无法正常工作,因为你仍然没有处理在Redis IO回调中找到/未找到的行为(也就是传递给'isPasswordInPwdHistory'的主回调) - 你在任何Redis回调之外的主要执行路径中处理它。你无法完成这项工作 - 它与丢失范围无关,而是执行代码的顺序。在Redis能够响应其结果之前,您正在调用'cb(match)' 。 –