我似乎在提出HEAD
请求时遇到了一些问题,并保留了数组中数据的完整性。
鉴于此片段:
var imageTemp = Array();
$('*')
.each(function(index){
if($(this).css('background-image') != 'none'){
imageTemp.push($(this).css('background-image').slice(5, -2));
}
});
我捕获给定页面上所有背景图像的URL。现在,尝试通过HEAD
的{{1}}请求获取每张图片的大小,我使用此代码段:
Content-Length
但是,当我通过var imageData = Array();
for(var i = 0; i < imageTemp.length; i++){
ajaxSizeRequest = $.ajax({
type: "HEAD",
async: true,
url: imageTemp[i],
success: function(message){
imageData.push([imageTemp[i], ajaxSizeRequest.getResponseHeader('Content-Length')]);
}
});
}
转储imageData
时,我的每个元素(应该是包含URL和内容长度的数组)最终为console.log
,其中{{1}始终是上次请求的[undefined, XXXX]
我很难过,虽然这似乎是一个时间/范围问题。我在这里会遇到某种竞争条件吗?
答案 0 :(得分:20)
问题是回调函数捕获的单个变量i
和ajaxSizeRequest
对于回调函数的所有实例都是相同的变量。我想如果你调用一个函数并将索引变量传递给它,同时将请求变量本地范围扩展到函数本身使用done处理程序的响应参数,你应该最终具有由回调捕获的自变量。然后它应该正确引用每个数组元素和每个响应变量。
var imageData = Array();
for(var i = 0; i < imageTemp.length; i++){
updateImageData( i );
}
function updateImageData( i )
$.ajax({
type: "HEAD",
async: true,
url: imageTemp[i],
}).done(function(message,text,jqXHR){
imageData.push([imageTemp[i], jqXHR.getResponseHeader('Content-Length')]);
});
}
答案 1 :(得分:2)
看起来i
未正确关闭
此外,你不能使用ajaxSizeRequest
,因为它也指向一个请求(可能是最后一个,因为循环执行速度非常快)
按如下方式打包您的success
回调函数,将引用更改为ajaxSizeRequest
:
success: (function(i){
return function(data,status,xhr){
imageData.push([imageTemp[i], xhr.getResponseHeader('Content-Length')]);
};
})(i)
答案 2 :(得分:1)
你可以这样做范围:
success: function(i){
return function(message){
imageData.push([imageTemp[i], ajaxSizeRequest.getResponseHeader('Content-Length')]);
}
}(i)
答案 3 :(得分:0)
您有一个i
变量,由所有回调共享
由于AJAX是异步的,所以所有回调都在循环结束后运行,并且它们都得到相同的i
。
要解决此问题,您需要将AJAX调用移动到以i
为参数的单独函数中。
因此,每个回调都将获得一个单独的i
参数。
答案 4 :(得分:0)
如果有人仍然遇到这个问题,并且由于这篇帖子已经有5年历史了,这里的答案就更加“现代”了:只需使用let
代替var
在原帖for
循环中。
信息:Is there any reason to use the “var” keyword in ES6? 并且:MDN - Let syntax