jQuery中的for循环中的AJAX调用

22

我对使用AJAX还很陌生,我正在编写一个用户脚本,将处理页面上的一堆链接,并为每个链接进行AJAX调用。

for (var i = 0; i < linkList.length; i++)
{
    $.ajax({
        url: linkList[i].getAttribute("href"),
        cache: false
    }).done(function( html )
    {
        var hasAppended = false;
        if (html.indexOf('someStringOnGottenPage') != -1 && !hasAppended)
        {
            hasAppended = true;
            var id = linkList[i].getAttribute("href").substring(linkList[i].getAttribute("href").indexOf('='));
            $( "#links a[href*='" + id + "']" ).append(' THIS PAGE CONTAINS SPECIFIED DATA');
        }
    });
}

简单来说,我有一个链接列表页面。我希望遍历每个链接并使用AJAX处理每个链接页面的内容,并报告该页面是否包含特定内容。

我的问题是用于遍历链接列表的[i]值始终为6,而它永远不应该是那样。我假设我需要传递一些数据,以便当.done最终触发时,它知道其在AJAX首次触发时的[i]值,而不是稍后触发.done时的[i]值。

我该如何确保.done在首次调用AJAX时知道它的[i]值?


1
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures#Creating_closures_in_loops.3A_A_common_mistake - Arun P Johny
linkList是什么,它是一个jQuery对象还是一个数组? - Arun P Johny
解决方案可能看起来像这样:http://jsfiddle.net/arunpjohny/2Da7Z/1/ - Arun P Johny
2个回答

45

最简单的方法是使用闭包。每当你在循环中有异步操作时,都可以使用这种方法。

for (var i .....) {
  asynchronousFunction(function() {
    use(i);
  }
}
在这段伪代码片段中,内部函数捕获了由i引用的存储位置。循环运行,i增加到其最终值,然后异步回调开始被调用,它们都查找完全相同的位置(而不是值)。
解决方案如下:
for (var i .....) {
  (function (i) {
    asynchronousFunction(function() {
      use(i);
    });
  })(i);
}

即将循环的整个内容包装在一个自执行函数中。

这里,外部变量i被传递到封装的自执行匿名函数中;这个独特值的位置被异步回调所捕获。这样,每个异步函数都有自己的值,在自执行函数调用的时刻确定。


4
加入 (function (i) { CODE })(i); 包装器完美地解决了问题,现在代码可以按预期运行。谢谢! - Edge
7
那就是“闭包”的意义所在。 - LazerSharks
1
你救了我的命。 - krummens
它抛出了:"async未定义" - Pedro Joaquín
@PedroJoaquin:首先,这个答案是在async成为关键字之前编写的。其次,这是一个伪代码,async在这里是一个元变量,代表任何接受回调函数的异步函数,就像use()是任何应该在回调函数中完成的任务的元变量一样。我将重命名async以使其与ES6兼容,但您仍然必须用实际使用的函数(例如OP中的$.ajax)替换它。 - Amadan

20
评论区的链接可以告诉你代码中的问题......但是你可以有比那些解释更好的解决方案。
尝试使用$.each()来遍历列表(假设它是一个数组),这样传递的回调将为每次迭代创建一个单独的闭包。
$.each(linkList, function (i, item) {
    $.ajax({
        url: item.getAttribute("href"),
        cache: false
    }).done(function (html) {
        var hasAppended = false;
        if (html.indexOf('someStringOnGottenPage') != -1 && !hasAppended) {
            hasAppended = true;
            var id = item.getAttribute("href").substring(item.getAttribute("href").indexOf('='));
            $("#links a[href*='" + id + "']").append(' THIS PAGE CONTAINS SPECIFIED DATA');
        }
    });
})

如果它是一个jQuery对象,则使用 .each()
linkList.each(function (i, item) {
    var $item = $(item),
        href = $item.attr("href");
    $.ajax({
        url: href,
        cache: false
    }).done(function (html) {
        var hasAppended = false;
        if (html.indexOf('someStringOnGottenPage') != -1 && !hasAppended) {
            hasAppended = true;
            var id = href.substring(href.indexOf('='));
            $("#links a[href*='" + id + "']").append(' THIS PAGE CONTAINS SPECIFIED DATA');
        }
    });
})

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接