【问题标题】:Why is jquery GET sending only one value in this loop?为什么 jquery GET 在这个循环中只发送一个值?
【发布时间】:2012-04-04 02:28:49
【问题描述】:

下面的函数应该为每个查询抓取视频并构造一些依赖于i的html

function getVideos() {

    var text = "";
    for(var i=0; i<queryArray.length; i++){
        var queryUrl = "http://gdata.youtube.com/feeds/api/videos?q="+queryArray[i]+
              "&max-results=1&orderby=relevance&v=2&alt=json&format=5";

     $.get(queryUrl, function(data){ 
    constructHtml(data, i);
    }, 'json');

    }

}

但是,每次调用$.get 时,它都会将i 作为2 传递给constructHtml,这是为什么呢? 注意:querryArray 中有两个值,因此"2" 在技术上超出范围。

【问题讨论】:

  • 进行 ajax 调用时,i 值不会嵌入到构造调用中。 JS 在执行 constructHTML 调用时提取 i 的可用值,这是在您的主 for 循环完成之后的某个时间,所以 i 应该几乎总是在循环退出后设置的 LAST 值。

标签: javascript jquery youtube-api


【解决方案1】:

这是因为 AJAX 调用是异步的,所以当成功回调运行时循环已经结束,i 的值就是循环结束时得到的值。

使用闭包为每次迭代保留i 的值:

function getVideos() {
  var text = "";
  for(var i=0; i<queryArray.length; i++){

    (function(index){

      var queryUrl = "http://gdata.youtube.com/feeds/api/videos?q="+queryArray[index]+
          "&max-results=1&orderby=relevance&v=2&alt=json&format=5";
      $.get(queryUrl, function(data){ 
        constructHtml(data, index);
      }, 'json');

    })(i);

  }
}

这是一个演示,它使用计时器来显示为异步回调保留变量值:http://jsfiddle.net/Guffa/WgxPC/

【讨论】:

  • 感谢您的洞察力!...虽然这不起作用...它仍然将 i 设置为 2... :(
  • @algorithmicCoder:您是否更改了代码,以便在函数内部使用函数参数,而不是i?
【解决方案2】:

由于$.get() 的默认异步性质,您的 for 循环继续执行并且您的 i 变量被重新分配。

解决此问题的快速方法是在您的$.get() 上设置async: false,这将基本上阻止您的for 循环继续执行,直到您的$.get() 完成,这意味着您的i 值在此过程中不会改变。

必须强调的是,这将阻止所有脚本在页面上执行,直到您的 for 循环完成,可能会在很长一段时间内阻止您的用户完成其他操作。

【讨论】:

  • 将 async 设置为 false 有效!..也许您可以改写您的回复以专注于该特定提示。谢谢!
  • 将 async 设置为 false 有效,但不建议这样做,因为它会在等待响应时冻结整个浏览器。
  • @Guffa 确实如此,我个人不推荐它,但替代方案将涉及退后几个级别并重新评估页面上的整个过程,以便找出最佳方法达到预期目的。
  • @SimonWest:这不是必需的,只需在循环中放置一个闭包。看我的回答。
【解决方案3】:

这是变量提升;变量总是被提升到函数范围,即使你在一个块中定义它们。

您定义的内联函数是“关闭”对 i 的引用,因此在调用constructHtml 时,它是最后一个值。尝试将其定义为更高范围的函数,并传递您的参数。

一些阅读:

http://oreilly.com/javascript/excerpts/javascript-good-parts/awful-parts.html

【讨论】:

    【解决方案4】:

    试试这个:

    function(index) {
        $.get(queryUrl, function(data){ 
        constructHtml(data, index);
        }, 'json');
    }(i);
    

    您的代码不起作用的原因是回调在循环完成时执行。因此,您可能会触发两个或更多 AJAX 操作,但当它们完成时,“i”现在是循环的结尾。

    【讨论】:

      【解决方案5】:

      因为当您的回调方法被调用时,for 循环已完成执行,并且i 设置为数组中的最高索引 + 1。该值为 2(即使只有 2 个项目),因为i++ 的执行次数比数组中的项目多 1 次。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-05
        • 2022-01-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-17
        相关资源
        最近更新 更多