Подтвердить что ты не робот

JQuery AJAX вызывает цикл for

Я новичок в использовании AJAX, и я пишу usercript, который обрабатывает кучу ссылок на странице и делает вызовы 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], используемое для итерации через linkList, всегда 6, и этого никогда не должно быть. Я предполагаю, что мне нужно передать некоторые данные, чтобы, когда .done, наконец, запускает, он знает свое значение [i] с момента запуска AJAX, а не значения [i], когда .done запускает позже.

Как мне обеспечить, что .done знает это значение [i], когда AJAX сначала вызывается?

4b9b3361

Ответ 1

Самый простой способ - использовать закрытие. Всякий раз, когда у вас есть что-то асинхронное в цикле, это одно и то же.

for (var i .....) {
  async(function() {
    use(i);
  }
}

В этом фрагменте псевдокода внутренняя функция фиксирует местоположение хранилища, на которое ссылается i. Цикл выполняется, значение i увеличивается до конечного значения, а затем вызываются вызовы async, все они ищут то же самое местоположение (не значение).

Общее решение таково:

for (var i .....) {
  (function (i) {
    async(function() {
      use(i);
    });
  })(i);
}

то есть. оберните все содержимое вашего цикла в функцию самоисполнения.

Здесь значение внешнего i передается в анонимную функцию обертывания; это уникальное местоположение значения захватывается асинхронным обратным вызовом. Таким образом, каждый async получает свое собственное значение, определенное в момент вызова функции самоисполнения.

Ответ 2

Ссылки в разделе комментариев вопроса говорят вам, что не так в вашем коде... но вы можете иметь лучшее решение, чем когда-то объясняемое там.

Попробуйте $. 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');
        }
    });
})