我的猜测是您的代码在您的 login() 方法的某处抛出了异常,并且由于大部分代码是在异步回调中执行的,您可能无法在控制台中获得任何异常信息。
这里有几个调试这个问题的建议:
您需要通过login() 方法遵循确切的流程。如果您在问题中所说的是真的,那么它有时不会调用回调,您需要找出原因。遵循流程的最简单方法是在login() 方法的每个分支中插入一个唯一标记的console.log() 语句,这样您就可以准确地看到控制流的方向以及执行的内容和不执行的内容。一旦你找到了,你就可以输出各种值来看看为什么会这样,或者设置一个适当的断点并跟踪它。
login() 方法或它调用的东西中也可能引发某种异常。如果您进入异步回调,异常可能不会记录在控制台中,因此事情可能会静默失败,并且可能只是跳过回调而控制台中没有显示任何内容。如果您怀疑某个特定位置存在异常,您可以将自己的异常处理程序放在那里并记录异常是什么。请记住,每个异步范围都需要自己的异常处理程序——您不能只在顶层使用一个异常处理程序。这是异步编码的复杂性,也是使用 Promise 代替普通回调更有用的一个原因,因为 Promise 系统将为您捕获所有异步异常并将其转换为以异常为原因的被拒绝的 Promise(因此异步异常不会不要默默地失败)。
如果您的 login() 方法执行 user.save() 代码分支,则存在逻辑问题。我已经在下面记录了这个问题,虽然我认为这不是你的主要问题 - 但它需要解决。
我还建议您将日志记录放在调用 UserEngine.login() 的位置,以便记录所有可能的回调值。
建议的日志记录:
UserEngine.login({
username: data.username,
password: data.password
}, function(err, user) {
// =========== Add this ============
console.log("UserEngine.login() callback");
console.log(err, user);
if (err) {
d('Bad Login. Username: ' + data.username);
return;
}
这是您的login() 方法中user.save() 路径的问题:
在您的login() 代码中,作为self._verifyToken() 函数调用的一部分,您需要更改以下内容:
login: function(args, callback) {
/**
* username [String]
* password [String]
*/
var self = this;
if (!args.username || !args.password) {
return callback(Error.genObj(Error.code.MISSING_PARAMS));
}
User.findOne({
username: args.username
}, function(err, user) {
console.log('[Debug] In User.findOne(...) Callback;');
if (err) {
return callback(Error.genObj(Error.code.INTERNAL));
}
if (!user) {
return callback(Error.genObj(Error.code.TOKEN_AUTH_FAILED));
}
if (self._generateHash({ password: args.password, salt: user.salt }) != user.password) {
return callback(Error.genObj(Error.code.TOKEN_AUTH_FAILED));
}
self._verifyToken({
token: user.token,
username: args.username,
key: Config.tokenKey
}, function(err) {
if (err) {
var token = self._generateToken({ username: args.username, key: Config.key });
user.token = token;
user.save(function(err) {
if (err) {
return callback(Error.genObj(Error.code.INTERNAL));
}
return callback(null, user);
});
}
return callback(null, user);
});
});
},
到这里:
login: function(args, callback) {
/**
* username [String]
* password [String]
*/
var self = this;
if (!args.username || !args.password) {
return callback(Error.genObj(Error.code.MISSING_PARAMS));
}
User.findOne({
username: args.username
}, function(err, user) {
console.log('[Debug] In User.findOne(...) Callback;');
if (err) {
return callback(Error.genObj(Error.code.INTERNAL));
}
if (!user) {
return callback(Error.genObj(Error.code.TOKEN_AUTH_FAILED));
}
if (self._generateHash({ password: args.password, salt: user.salt }) != user.password) {
return callback(Error.genObj(Error.code.TOKEN_AUTH_FAILED));
}
self._verifyToken({
token: user.token,
username: args.username,
key: Config.tokenKey
}, function(err) {
if (err) {
var token = self._generateToken({ username: args.username, key: Config.key });
user.token = token;
user.save(function(err) {
if (err) {
return callback(Error.genObj(Error.code.INTERNAL));
}
return callback(null, user);
});
} else {
// ======== put this in an else clause ==========
return callback(null, user);
}
});
});
},
问题是,如果你从verifyToken() 收到错误,那么它将启动user.save(),但由于这是异步的,它会在user.save() 操作完成之前继续并执行return callback(null, user) 然后它user.save() 完成后会再次调用回调。