【问题标题】:Ajax HEAD request via Javascript/jQuery通过 Javascript/jQuery 的 Ajax HEAD 请求
【发布时间】:2011-06-10 13:20:45
【问题描述】:

我在发出 HEAD 请求和保持数组中数据的完整性时似乎遇到了一些问题。

鉴于这个 sn-p:

var imageTemp = Array();

$('*')
    .each(function(index){
        if($(this).css('background-image') != 'none'){
            imageTemp.push($(this).css('background-image').slice(5, -2));
        }
    });

我捕获给定页面上所有背景图像的 URL。现在,尝试通过HEAD 请求Content-Length 来获取每个图像的大小,我使用了这个sn-p:

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 转储 imageData 时,我每个元素(应该是一个包含 URL 和内容长度的数组)都以 [undefined, XXXX] 结尾,其中 XXXX 始终是最后请求Content-Length

我很困惑,尽管这似乎是一个时间/范围问题。我这里发生了某种竞争情况吗?

【问题讨论】:

  • 你可以使用success回调的第二个参数来代替ajaxSizeRequest变量。

标签: javascript jquery ajax http-headers


【解决方案1】:

您有一个由所有回调共享的 i 变量。
由于 AJAX 是异步的,所有的回调在你的循环结束后运行,它们都得到相同的i

要解决此问题,您需要将 AJAX 调用移动到一个单独的函数中,该函数将 i 作为参数。
因此,每个回调都会获得一个单独的i 参数。

【讨论】:

    【解决方案2】:

    您的 i 似乎没有正确关闭

    另外,你不能使用ajaxSizeRequest,因为它也只指向一个请求(可能是最后一个,因为循环会执行得非常快)

    只需将success 回调函数包装如下,将引用更改为ajaxSizeRequest

    success: (function(i){
       return function(data,status,xhr){
         imageData.push([imageTemp[i], xhr.getResponseHeader('Content-Length')]);
       };
    })(i)
    

    【讨论】:

      【解决方案3】:

      你可以这样定义我喜欢的范围:

      success: function(i){
          return function(message){
              imageData.push([imageTemp[i], ajaxSizeRequest.getResponseHeader('Content-Length')]);
          }
      }(i)
      

      【讨论】:

        【解决方案4】:

        问题是回调函数捕获的单个变量iajaxSizeRequest 对于回调函数的所有实例都是相同的变量。我认为如果你调用一个函数并将索引变量传递给它,同时,将请求变量的范围限定为函数本身使用完成处理程序的响应参数,你应该结束由回调捕获的自变量。然后它应该正确引用每个数组元素和每个响应变量。

        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')]);
            });
        }
        

        【讨论】:

        • 非常感谢 tvanfosson;这就像一个魅力。我匿名了updateImageData 以避免污染我的脚本。
        • 避免使用success,防止代码混乱!改用.done(function(text, status, xhr){ ...... };
        • @EladKarako - 很老的答案,我已经更新以反映当前的最佳实践。
        • 感谢您的更新,顺便说一句,答案是永恒的;)(.....嗯.. 至少谷歌会在前 5 个结果中提出建议)。跨度>
        【解决方案5】:

        如果有人仍然对此有疑问,并且由于这篇文章已经有 5 年的历史,这里有一个更“现代”的答案版本:只需在原始帖子中使用 let 而不是 var for 循环。

        信息:Is there any reason to use the “var” keyword in ES6? 和:MDN - Let syntax

        【讨论】:

          猜你喜欢
          • 2013-01-09
          • 1970-01-01
          • 1970-01-01
          • 2015-04-21
          • 2012-05-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多