我正在尝试将一些Javascript函数推送到数组中以使用jQuery.when()调用它们,但是当这样做时,函数在放入数组时已经被调用。 Here's an example这是我的代码段:
var answers = someJSONFormattedData;
var calls = [];
function callWithIndex(i) {
var answer = answers[i];
api.loadUser(answer.userType, answer.userId, function(userData) {
answer.user = userData;
}, null)
};
for(var i=0;i<answers.length;++i) {
calls.push(callWithIndex(i));
}
$.when.apply($, calls).then(function() {
var dataAsJSON = {
'answers': answers
};
//do some magic stuff with dataAsJSON
});
即使在做一个简短的测试代码片段时,也会立即调用test()函数,尽管我根本不会调用它,因为我只将它放入一个数组中(或至少尝试)。
var test = function(i) {
console.log("test: "+i);
}
var testArray = [];
for(var i=0;i<5;++i) {
testArray.push(test(i));
}
答案 0 :(得分:5)
您需要push
对该函数的引用,而不是其(undefined
)结果的引用:
试试这个:
calls.push(callWithIndex.bind(null, i));
答案 1 :(得分:0)
首先,感谢所有人,但事实证明问题是另一回事。问题不在于数组中的函数是立即调用的,而是在callWithIndex函数中的ajax调用完成之前执行了done()函数。
在数组中的函数完成后调用done的正确方法是让传递的函数返回其内部ajax()调用的返回值(在我的例子中)包装在api.loadUser中)。
据我所知,jQuery的ajax调用返回一个Deferred对象,并且只要在when()函数中传递的所有Deferred对象都完成,就会调用done()函数。 Imho,这在jQuery文档中并没有很好地记录,他们只是使用ajax()调用,而没有提到返回值在这里诀窍。
Here你会找到一个很好的关于jQuery的教程(...)完成(...)的东西
所以最后,我的代码如下:
在我的api命名空间中,我定义了loadUser函数,该函数现在返回ajax返回值
api.loadUser = function(userType, userId, onSuccess, onError) {
return $.ajax({
//do your ajax stuff
});
};
在我目前的JavaScript文件中,它现在看起来如下:
var collectedData = [];
var callWithIndex = function(i, userType, userId) {
return api.loadUser(userType, userId, function(data) {
collectedData.push(data);
});
}
var deferreds = [];
for(var i=0;i<someData.length;++i) {
var entry = someData[i];
deferreds.push(callWithIndex(i, entry.userType, entry.userId));
}
$.when.apply($, deferreds).done(function(result) {
// do stuff with collectedData
});
到目前为止,这对我有用,现在在完成所有callWithIndex调用时调用done()。
我没有使用的原因
deferreds.push(api.loadUser(answer.userType, answer.userId, function(data) {
//do stuff with collectedData
}));
是对于loadUser()的成功函数未定义的collectData数组。我想这是与范围相关的问题,但我不在乎。