“但是,如果我在函数完成后记录它,......”
通过这个我假设你正在做这样的事情......
var user = new User
user.populate();
console.log(user);
如果是这样,将在调用异步回调console.log
之前很久运行。.findOne()
任何依赖于响应的代码都findOne
需要在回调中调用。
编辑:您的更新与我上面的示例略有不同,但原因是相同的。
将回调传递给该findOne
方法的全部原因是它执行异步活动。如果没有,则没有理由进行回调。您只需将内部代码直接放在对 的调用之后findOne
,就像对console.log()
.
但是因为它是异步的,所以后面的代码不会等待执行。这就是您在控制台中获取未填充对象的原因。
如果为每个添加标签console.log()
,您会看到它们执行无序。
var that = this;
db.collection("Users").findOne({email : that.email}, function(err, doc){
if(!err) {
that.firstName = doc.firstName;
that.lastName = doc.lastName;
that.password = doc.password;
}
console.log("inside the callback", that); // this happens Last!!!
});
console.log("outside the callback", that); // this happens First!!!
因此,一旦您观察到调用的顺序,就会清楚地console.log
知道空的调用发生在回调内部的调用之前。
编辑:您还可以让您的.populate()
方法接收在回调中调用的.findOne
回调。
User.prototype.createNickName = function () {
this.nickname = this.firstName.slice(0,3) + '_' + this.lastName.slice(0,3);
};
// >>>------------------------------v----receive a function argument...
User.prototype.populate = function(callback_func) {
var that = this;
db.collection("Users").findOne({email : that.email}, function(err, doc){
if(!err) {
that.firstName = doc.firstName;
that.lastName = doc.lastName;
that.password = doc.password;
}
// all users will have the "createNickName()" method invoked
that.createNickName();
// ...and invoke it in the callback.
callback_func.call(that);
// By using .call(), I'm setting the "this" value
// of callback_func to whatever is passed as the first argument
});
};
// this user wants to log the firstName property in all caps
var user1 = new User;
user1.populate(function() {
console.log(this.firstName.toUpperCase());
});
// this user wants to log the the whole name
var user2 = new User;
user2.populate(function() {
console.log(this.firstName + ' ' + this.lastName);
});
// this user wants to verify that the password is sufficiently secure
var user3 = new User;
user3.populate(function() {
console.log(verify_password(this.password));
});