Javascript 生成具有异步构造函数的对象数组
我想对NodeJS执行以下操作。创建一个包含以下内容的对象数组,其中每个对象在初始化时都有不同的局部变量 obj.jsJavascript 生成具有异步构造函数的对象数组,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) {
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')代码>