Почему jquery GET отправляет только одно значение в этом цикле? - PullRequest
0 голосов
/ 19 марта 2012

Предполагается, что приведенная ниже функция захватывает видео для каждого запроса и создает html, который зависит от i

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

    }

}

однако он передает i как 2 в constructHtml каждый раз, когда вызывается $.get Почему это так? Примечание: в querryArray есть два значения, поэтому технически "2" выходит за пределы.

Ответы [ 5 ]

1 голос
/ 19 марта 2012

Из-за асинхронного характера по умолчанию $.get() ваш цикл for продолжает выполняться, а ваша переменная i переназначается.

Быстрый способ исправить это - установить async: false на $.get(), что по существу не позволит циклу for продолжить выполнение до тех пор, пока не завершится $.get(), то есть значение i не изменится в процессе.

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

0 голосов
/ 19 марта 2012

Это потому, что вызов 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/

0 голосов
/ 19 марта 2012

Попробуйте это:

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

Причина, по которой ваш код не работает, заключается в том, что обратный вызов выполняется во время выполнения цикла. Таким образом, вы можете запустить две или более AJAX-операции, но к тому времени, когда они будут выполнены, «i» теперь является концом цикла.

0 голосов
/ 19 марта 2012

Это переменный подъем;Переменные всегда выводятся в область действия функции, даже если вы определяете их в блоке.

Определяемая вами встроенная функция является «закрывающей» ссылкой на i, поэтому к моменту вызова constructHtml это последнее значение.Попробуйте определить его как функцию с большей областью действия и передать свои аргументы.

Некоторое чтение:

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

0 голосов
/ 19 марта 2012

Поскольку к тому времени, когда ваш метод обратного вызова вызывается, цикл for уже завершил выполнение, а i имеет самый высокий индекс в вашем массиве + 1. Значение равно 2 (хотя есть только 2 элемента), потому что i++ выполняется в 1 раз больше, чем есть элементы в вашем массиве.

...