需要将异步数据库对象构造为父对象的属性

时间:2014-04-08 20:25:31

标签: javascript node.js asynchronous constructor mongoose

我有一个User对象,在其构造函数中创建一个mongoose数据库对象。

mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/Data');
var db = mongoose.connection;

UserSchema = new mongoose.Schema({
    username: String,
    salt: String,
    hash: String,
});
UserDB = mongoose.model('users', UserSchema);

function User(id) {
    var self = this;
    if (id)
        UserDB.findById(id, function(err, user) { // async
            if (!err && user)
                self.db = user;
        });
}

但是当我创建用户对象时,由于它是异步数据库调用,因此不会立即创建UserDB

user = new User('53179fd401d540b8c5000001');

if (user.db)
    console.log('fail '+user.db.id); // fails because !user.db yet
else
    setTimeout(function() {
        if (user.db)
            console.log('pass '+user.db.id); // only now it works
    }, 1000);

我能做什么,除非创建了DB对象,否则构造函数不会返回,或者其他什么东西不能让我做不可靠的setTimeout?

2 个答案:

答案 0 :(得分:0)

有许多可能性可以阻止这种情况。

事实是,您的数据库会像您正确说的那样实例化异步。

V1:您可以将回调传递给用户构造函数参数。

function User(id, ready) {
    var self = this;
    if (id)
        UserDB.findById(id, function(err, user) { // async
            if (!err && user)
                self.db = user;

            if(ready !== undefined)
                ready.call(this);
        });
}


new User(1, function() {
    console.log(this); // <- your users instance
});

V2:否则你需要一个用户(生产者消费者模式)的事件队列,在所有实例化后都会被调度。

V3:使用JQuery事件,然后调用$ .when方法收集多个回调。

v4:编写自己的回调队列以同步回调。

答案 1 :(得分:0)

想象我使用了承诺

var when = require('when');
function User(id) {
    var d = when.defer();
    this.ready = d.promise;

    var self = this;
    if (id)
        UserDB.findById(id, function(err, user) { // async
            if (!err && user){
                self.db = user;
                d.resolve();
}       }); }

user = new User('53179fd401d540b8c5000001');
user.ready.then(function(){
    console.log(user.db.id);
});