我正在尝试创建一个对象数组,然后访问数组中的对象属性,但它返回undefined。我调用createObjArray()函数后立即执行console.log(objArray [1]);并打印出所有它的对象... s属性就好了。但是,如果我尝试执行console.log(objArray [1] .name);萤火虫打印“未定义”。此外,当我在firebug中单步执行代码时,我可以将鼠标悬停在objArray [1] .name上,它会显示正确的名称。这里发生了什么,这让我疯狂。
var objArray = [];
function createObjectArray(numOfObjs) {
for(var i=0; i<numOfObjs; i++) {
packages.push(initObj(i));
}
}
function initObj(i){
var newPackage;
var p = {};
$.getJSON('.../package' + i + '.json', function(data) {
newPackage = new Package(data);
p.name = newPackage.name;
p.id = i;
});
return p;
}
答案 0 :(得分:1)
这将有效:
var objArray = [];
function createObjectArray(numOfObjs, callback) {
var filledPackage = [];
var nbLeft = numOfObjs;
for(var i=0; i<numOfObjs; i++) {
initObj(i, function(p){
filledPackage.push(p);
nbLeft--;
if (nbLeft === 0){
callback(filledPackage);
}
});
}
}
function initObj(i, callback){
var newPackage;
var p = {};
$.getJSON('.../package' + i + '.json', function(data) {
newPackage = new Package(data);
p.name = newPackage.name;
p.id = i;
callback(p);
});
}
//Get a filled object array:
createObjectArray(5, function(filledArray){
objArray = filledArray;
//Code here will be executed AFTER all the $.getJSON queries have returned.
//objArray is not empty.
});
//Code here will be executed WHILE the getJSON queries are running and
//while objArray is still empty. Due to the way the JS event loop works,
//it is impossible that code placed here will be able to use the content
//of objArray unless you call an async function such as anything AJAX or
//setTimeout, but that's iffy. Code you want to be executed once objArray
//has been filled should be inside of the callback above.
问题是$ .getJSON是异步的,这意味着它不会自动返回结果。相反,你给它一个回调。回调是一旦收到结果就要执行的函数。在这种情况下,回调是调用$ .getJSON时创建的匿名函数。该回调从服务器接收结果,将其添加到数组,然后检查数组是否已填充。由于$ .getJSON函数我们正在执行异步代码,因此我们必须异步返回结果。为此,我们要求initObj函数在完成后接收一个函数(另一个回调)。我们称之为回调并将参数传递给它。然后我们再次通过回调返回填充的数组。
答案 1 :(得分:0)
您对$ .getJSON的调用是异步的。当initObj()返回p时,它仍然是一个空对象。
然而,initObj()创建了一个闭包,它捕获对p的引用,这样当$ .getJSON返回p时就会被填充。
这就是在填充数组后立即运行的代码中对象似乎为空的原因。但是,当您运行控制台命令时,已返回异步调用并填充了对象。
在继续处理数组之前,您需要等待所有异步调用返回。执行此操作的一种方法是在进行调用时递增计数器,并在调用返回时递减计数器,然后在最终调用返回时计数器将降至零并继续处理。
或者你可以设置一个setTimout循环,以便在填充所有项目时对数组进行轮询。
如果您认为其中一个调用可能会失败,则这两种方法都存在风险,但是当您进行多个ajax调用时,这种方法本身就存在风险,因此您必须处理多个可能的失败。一次性获取所有数据会更加清晰,因此您可以在jQuery.ajax中的成功/错误处理程序中处理成功/错误状态一次。