Javascript 生成具有异步构造函数的对象数组

Javascript 生成具有异步构造函数的对象数组,javascript,node.js,object,asynchronous,callback,Javascript,Node.js,Object,Asynchronous,Callback,我想对NodeJS执行以下操作。创建一个包含以下内容的对象数组,其中每个对象在初始化时都有不同的局部变量 obj.js var Obj = function (_id) { this.id = _id; var that=this; db.getData(_id,function(collection){ //this method is asynchronous collection.toArray(function(err, items) {

我想对NodeJS执行以下操作。创建一个包含以下内容的对象数组,其中每个对象在初始化时都有不同的局部变量

obj.js

var Obj = function (_id) {
    this.id = _id;
    var that=this;
    db.getData(_id,function(collection){ //this method is asynchronous 

        collection.toArray(function(err, items) {
            that.data=items;
        });
    });
}

Obj.prototype.data = [];  

module.exports = Obj;
var arr=[];
arr.push(new obj(24));
arr.push(new obj(41));
arr.push(new obj(24));
arr.push(new obj(42));
//then do tasks with the arr
app.js

var Obj = function (_id) {
    this.id = _id;
    var that=this;
    db.getData(_id,function(collection){ //this method is asynchronous 

        collection.toArray(function(err, items) {
            that.data=items;
        });
    });
}

Obj.prototype.data = [];  

module.exports = Obj;
var arr=[];
arr.push(new obj(24));
arr.push(new obj(41));
arr.push(new obj(24));
arr.push(new obj(42));
//then do tasks with the arr
但是,由于arr构造函数是同步的,当我使用arr进行计算时,它们可能没有获得所有数据。那么如何处理这种情况呢?我想确保所有对象在使用它们之前都已成功创建


提前谢谢。

我会使用承诺模式。这里是这种方法的原型。我使用本机浏览器Promise进行实现和测试。对于NodeJS,您可以将Kowal的Q实现与类似(或非常接近)的API一起使用

其思想是,当
objFactory
返回的promise对象解析时,它将调用相应的
,然后
回调,在回调中,它可以可靠地处理
数据
,因为此时肯定会填充它

这是我用来测试代码的浏览器。您必须在NodeJS环境中采用它。但想法仍然是一样的

例如,使用Kris Kowal的Q,它将是这样的:

this.promise = function() {
    var deferred = Q.defer();
    db.getData(_id, function (collection) {
        collection.toArray(function (err, items) {
            that.data.push(items);
            deferred.resolve(that);
        });
    });
    return deferred.promise;
}();

还有
Q.all
而不是
Promise.all

伙计,@mscdex所说的是正确的。 首先,在您的代码中,
数据将在内存中共享,您应该在构造函数中使用
this.data=[]
。 其次,正如@mscdex所说的,将您的方法移动到原型中,比如

Obj.prototype.load=function(){
    //code here...
}
那么您的代码如下所示:

var Obj = function(_id){
    this.id=_id;
    this.data = [];
}
Obj.prototype.load = function(){
    var that = this;
    db.getData(this.id,function(collection){ //this method is asynchronous
        collection.toArray(function(err, items) {
            that.data=items;
        });
    });
    return that;
}
最后,你的问题是,你怎么知道他们都准备好了

Obj.prototype.ready = [];
Obj.prototype.loaded=function(){
    this.ready.push(1);
    if(this.ready.length == Obj.target)
        Obj.onComplete();
}
Obj.notifyme = function(callback,len){
    Obj.target = len;
    Obj.onComplete = callback;
}
上面的代码设置了一个数组来计数加载完成的实例(使用数组是因为无法从实例的
\uuuu proto\uu
引用中读取基本值)。因此,您应该做的是将此事件(函数)添加到
load
,这样代码最终可能如下所示:

Obj.prototype.load = function(){
    var that = this;
    db.getData(this.id,function(collection){ //this method is asynchronous
        collection.toArray(function(err, items) {
            that.data=items;
            that.loaded();
        });
    });
    return that;
}
var args = [24,41,42];
Obj.notifyme(function(){/*then do tasks with the arr*/},args.length);
var arr = args.map(function(arg){
    return new Obj(arg).load();
});

告诉函数
notifyme
回调工作和实例数。最后一个问题是,如果您多次执行此例程,您应该重置
target
callback
,因为它们是
Obj
全局对象。

在构造函数中执行异步工作非常尴尬,为什么不将该工作转移到原型函数中?另一个不相关的问题是,为什么要创建共享数组
数据
?似乎您将
data
用作每个实例变量,而不是所有
Obj
实例共享的变量。@msdex数据与每个对象不同:)我可以将异步工作移动到另一个原型方法。那么,我如何确保异步工作已经完成呢?:)在实例上设置一个标志,然后签入依赖
数据的其他原型函数。另外,要使
data
成为每个实例的变量,可以删除
Obj.prototype.data=[]this.data=[]就在构造函数内部。或者你可以用它作为你的标志——首先设置
this.data=undefined然后在原型函数中执行如下操作:
如果(!this.data)抛出新错误('No data')