【问题标题】:jQuery scope or race condition in AJAX/getJSONAJAX/getJSON 中的 jQuery 范围或竞争条件
【发布时间】:2010-10-01 11:42:27
【问题描述】:

我有一段 jQuery 代码可以快速连续调用多个 getJSON()

var table = $("table#output");
for (var i in items) {
    var thisItem = items[i];
    $.getJSON("myService", { "itemID": thisItem }, function(json) {
        var str = "<tr>";
        str += "<td>" + thisItem + "</td>";
        str += "<td>" + json.someMember + "</td>";
        str += "</tr>";
        table.append(str);
    });
}

当我在一台滞后的服务器上运行此程序时,该表会填充预期的 json.someMember 值(它们无序到达:我不介意),但 thisItem 列填充了不可预知的混合物来自各种迭代的值。

我假设这与范围和时间有关 - 回调函数正在从更广泛的范围读取 thisItem?我对吗?如何防止这种情况发生?

我目前的解决方法是让 JSON 服务返回其输入的副本 - 至少可以说是不令人满意的。

【问题讨论】:

  • 感谢 Slim 提出这个问题。我也遇到了一些问题(我知道异步函数返回,但不知道如何用信号通知 getJSON 回调在什么位置放置返回值)。

标签: javascript jquery ajax json timing


【解决方案1】:

由于循环,这似乎是一个范围问题。试试这个:

var table = $("table#output");
for (var i in items) {
    var thisItem = items[i];
    $.getJSON("myService", { "itemID": thisItem }, (function(thisItem) {
        return function(json) {
            var str = "<tr>";
            str += "<td>" + thisItem + "</td>";
            str += "<td>" + json.someMember + "</td>";
            str += "</tr>";
            table.append(str);
        }
    })(thisItem));
}

编辑:我所做的只是将thisItem 作用于$.getJSON 回调。

【讨论】:

  • 我认为这不适用于 jQuery。 json 最终不会被传递到闭包而不是 thisItem 变量中并导致错误吗?
  • 没有。 $.getJSON 被传递到内部函数;获得“json”参数的那个。
  • 似乎奏效了(在我整理好所有牙套之后!)。谢谢!
  • 感谢 Crescent Fresh,必须传入我想要填充的图像表的索引(被异步返回烧毁,即使我知道它们不知道如何确定它的范围)。通过索引就像一个魅力!
【解决方案2】:

Javascript 不使用块作为范围。范围仅基于函数。

如果你想要一个新的作用域,你必须声明一个新的内部函数并立即运行它,这是在 Javascript 中创建新作用域的唯一方法。

var table = $("table#output");
for( var i in items ) 
{
    (function(){
        var thisItem = items[i];
        $.getJSON("myService", { "itemID": thisItem }, function(json) 
        {
            var str = "<tr>";
            str += "<td>" + thisItem + "</td>";
            str += "<td>" + json.someMember + "</td>";
            str += "</tr>";
            table.append(str);
        });
    })();
}

【讨论】:

  • 我喜欢这个解决方案,因为它允许我拥有更多像 thisItem 这样的局部变量,而无需冗长的函数签名。
  • 有趣的事实:这就是 Scheme 中通常实现范围的方式
  • 我忘记了另一种方法,您可以使用库中的 for 循环,这些实际上将函数作为在每次迭代时执行的块。在 jQuery 中: $.each(items, function(i, item){ ... });
  • 非常感谢文森特。我被异步回调的作用域烧毁了。封装了一个传递的索引,以知道将我的回报和鲸鱼放在哪里!
猜你喜欢
  • 1970-01-01
  • 2011-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-03
  • 1970-01-01
  • 1970-01-01
  • 2016-03-07
相关资源
最近更新 更多