通过Javascript / jQuery的Ajax HEAD请求
我似乎在制作HEAD
请求时遇到了一些问题,并保留了数组中数据的完整性。
鉴于此片段:
var imageTemp = Array(); $('*') .each(function(index){ if($(this).css('background-image') != 'none'){ imageTemp.push($(this).css('background-image').slice(5, -2)); } });
我捕捉给定页面上的所有背景图像的URL。 现在,试图通过对Content-Length
HEAD
请求获取每个图像的大小,我使用这个片段:
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')]); } }); }
但是,当我通过console.log
dump imageData
时,每个元素(应该是一个包含URL和内容长度的数组)结束为[undefined, XXXX]
,其中XXXX
总是最后请求的Content-Length
的大小
我很困惑,虽然这似乎是一个时间/范围问题。 我在这里遇到种族情况吗?
问题是callback函数捕获的单个variablesi
和ajaxSizeRequest
对于callback函数的所有实例都是相同的variables。 我认为,如果你调用一个函数并将索引variables传递给它,并且同时将请求variables的范围局限于函数本身,则使用done处理程序的响应参数,最终应该由callback捕获的独立variables。 然后它应该正确引用每个数组元素和每个响应variables。
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')]); }); }
看起来像你i
正确封闭
另外,你不能使用ajaxSizeRequest
因为它也只指向一个请求(可能是最后一个,因为循环执行速度非常快)
只需包装你的success
callback函数,如下所示,更改引用ajaxSizeRequest
:
success: (function(i){ return function(data,status,xhr){ imageData.push([imageTemp[i], xhr.getResponseHeader('Content-Length')]); }; })(i)
你可以像我这样的范围:
success: function(i){ return function(message){ imageData.push([imageTemp[i], ajaxSizeRequest.getResponseHeader('Content-Length')]); } }(i)
你有一个单一的i
所有的callback共享的variables。
由于AJAX是asynchronous的,所有的callback在你的循环完成后运行,并且它们都得到相同的i
。
为了解决这个问题,你需要把AJAX调用转换成一个独立的函数,把i
作为参数。
因此,每个callback将获得一个单独的i
参数。
如果任何人仍然遇到这个问题,并且自从这篇文章已经有5年的历史,那么下面是一个更“现代”的答案:只要在原始文章的for
循环中使用let
而不是var
。
信息: 是否有任何理由在ES6中使用“var”关键字? 和: MDN – 让语法