我使用此处发布的ajax-request队列:Wait until all jQuery Ajax requests are done?
现在我编写了以下代码来实现它:
for (var i=0; i<3; i++) {
$.ajaxQueue({
url: '/action/',
data: {action:'previous',item:i*-1},
type: 'GET',
success: function(data) {
$('.item-history .itemlist').prepend(data['item_add']);
$('.item-history .itemlist:first .index').html(data['newitemindex']);
//alert(data['newitemindex'])
};
});
只要我使用警报来证明来自服务器的响应,一切正常。但是一旦我运行代码,如图所示,没有警报,data ['newitemindex']就像它是一个全局变量一样 - 它总是返回最后一项的值。
我试图在此设置一个jsfiddle,但由于我从未使用过那个网站,我无法让ajax工作。如果有人想看一下它:http://jsfiddle.net/marue/UfH5M/26/
答案 0 :(得分:3)
您的代码正在设置三个ajax调用,然后将每个调用的结果应用于相同的元素(您在success
函数中使用的选择器没有区别) 。对于$('.item-history .itemlist')
元素,您应该看到每个调用前置的结果,因为您使用的是prepend()
,但对于$('.item-history .itemlist:first .index')
元素,您'使用html()
替换元素的内容,因此对于那些你会看到完成的最后一次调用的结果。
偏离主题:要解决此问题,您可能希望在success
函数中以某种方式使用循环变量。这可能会导致一个常见的错误,所以这里有一个错误的例子,以及如何避免错误。
假设我有这些div:
<div id='div1'></div>
<div id='div2'></div>
<div id='div3'></div>
当我点击按钮时,我想使用三个ajax调用来填充它们,使用从1
到3
的循环计数器。我想我可以这样做:
$('#btnGo').click(function() {
var i;
for (i = 1; i <= 3; ++i) {
$.ajax({
url: "/agiba4/" + i,
dataType: "text",
success: function(data) {
// THIS NEXT LINE IS WRONG
$('#div' + i).html(data);
},
error: function(xhr, status, err) {
$("<p/>").html(
"Error, status = " + status + ", err = " + err
).appendTo(document.body);
}
});
}
});
Live example (失败)
但是(如图所示)不起作用。它不起作用,因为我们创建的每个success
函数都有{em>持久引用到i
变量,不它的值的副本何时创建success
函数。因此,所有三个success
函数都会看到i
的相同值,这是函数运行时的值 - 在循环完成后很久。所以(在这个例子中),它们都看到值4
(循环结束后i
的值)。这就是闭包的工作方式(参见:Closures are not complicated)。
要解决此问题,请对其进行设置,以便success
函数关闭不会被循环更新的内容。最简单的方法是将循环计数器作为参数传递给另一个函数,然后让success
函数关闭该参数,因为参数是循环计数器的 copy ,将不会更新:
$('#btnGo').click(function() {
var i;
for (i = 1; i <= 3; ++i) {
doRequest(i);
}
function doRequest(index) {
$.ajax({
url: "/agiba4/" + index,
dataType: "text",
success: function(data) {
$('#div' + index).html(data);
},
error: function(xhr, status, err) {
$("<p/>").html(
"Error, status = " + status + ", err = " + err
).appendTo(document.body);
}
});
}
});