Асинхронный вызов AJAX выводит моих итераторов из строя - PullRequest
0 голосов
/ 23 ноября 2011

Я использую следующий AJAX-запрос для получения количества страниц, заголовки которых у меня есть в массиве с именем pages. Каждый ответ помещается в отдельный элемент div, и я хочу присвоить каждому из этих элементов div идентификатор, идентичный заголовку страницы.

Конечно, к тому времени, когда мои запросы вернутся, [i] достигнет pages.length, и все мои имена div undefined.

for ( i = 0; i < pages.length; i++ ) {
  $.ajax({
    //async:false makes it work but it slows things down too much
    url: 'ajax_' + pages[i],
    success: function(data) {
      $('<div id="' + pages[i] + '">' + data + '</div>').appendTo('div.content');
      }
  });
 }

Как мне получить хороший шаг между запрашивающей и отвечающей переменными?

Спасибо!

NB Я бы предпочел оставить его асинхронным (т.е. не использовать async:false).

Ответы [ 3 ]

1 голос
/ 23 ноября 2011

Быстро и грязно:

$.ajax({
    url: 'ajax_' + pages[i],

    context: i, // set `this` to `i` in the callback

    success: function(data) {
        // `this` is the correct, "frozen" `i`
        $('<div id="' + pages[this] + '">' + data + '</div>').appendTo('div.content');
    }
});

Обратите внимание, что this всегда приводится в объект - как new Number(2) вместо 2.Тем не менее, они могут использоваться для доступа к индексам массива.

Есть более чистые способы сделать это, например, создать замыкание, но это может сработать для вас (то есть, если вы не используете this для чего-либо еще)в обратном вызове).

0 голосов
/ 23 ноября 2011

В JavaScript есть нечто, называемое лексической областью действия, которое отличается от области видимости блоков, с которой большинство знакомо.В JS, чтобы дать что-то новое, он должен быть внутри другой функции, а не только в фигурных скобках {}.

Причина, по которой async: false работает, заключается в том, что вы заставляете его ждать ответа додвигаться дальше, что позволяет избежать проблемы с областью действия.

Попробуйте:

for ( i = 0; i < pages.length; i++ ) {
    $.ajax({
        //async:false makes it work but it slows things down too much
        url: 'ajax_' + pages[i],
        success: (function(index){ 
              return function(data) {
                  $('<div id="' + pages[i] + '">' + data + '</div>').appendTo('div.content');
              };
        })(i)
    });
}
0 голосов
/ 23 ноября 2011

Вы всегда должны использовать ключевое слово var в переменных цикла for для правильной их области видимости. В противном случае этот цикл обращается к глобальной переменной i, которая может или не может конфликтовать с другим циклом.

Но это не решение проблемы, которая у вас есть. Вам необходимо кэшировать ссылку на текущую страницу и использовать ее в ответе ajax.

for ( var i = 0; i < pages.length; i++ ) {
  var page = pages[i];
  $.ajax({
    //async:false makes it work but it slows things down too much
    url: 'ajax_' + page,
    success: function(data) {
      $('<div id="' + page + '">' + data + '</div>').appendTo('div.content');
      }
  });
 }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...