Вызов AJAX для цикла не возвращает значения для исправления позиций массива - PullRequest
16 голосов
/ 09 марта 2010

Мне нужно получить диапазон страниц с помощью AJAX и поместить их в массив, где их заданное место в массиве равно i цикла for (это функция, подобная кешированию для страниц блога, и диапазон цикла for является полностью переменным). Я делаю что-то похожее на следующее:

var bongo = new Array();

for (i = 0; i < 10; i++) {

    jQuery.ajax({ type: "GET", url: 'http://localhost', data: queryString, success: function(request) { bongo[i] = request } })

}

Проблема в том, что если я не добавлю async: false к параметрам .ajax (что сделает это ... SJAX?), Что заставит запросы в основном приостанавливать работу браузера, что противоречит тому, что я пытаюсь сделать , i в успешном обратном вызове всегда будет 11, тогда как я, конечно, хочу, чтобы он возвращал возвращаемые данные в каждый слот массива от 0 до 10.

Я пытался заменить строку следующим образом:

bongo[i] = jQuery.ajax({ type: "GET", url: 'http://localhost', data: queryString }).responseText

Но это не имело значения.

Ответы [ 2 ]

39 голосов
/ 09 марта 2010

Вам нужно закрытие:

var bongo = [];
for (i = 0; i < 10; i++)
{

  (function(i)
    {
      jQuery.ajax(
        {
          type: "GET",
          url: "http://localhost",
          data: queryString,
          success: function(request) { bongo[i] = request } 
        });  
    })(i);
}

Циклы - это место № 1, где встроенные функции ставят людей в тупик. bongo[i] = result не вызывается до позже. Значение i в это время отличается (скорее всего, 11). Если вы хотите «перехватить» или «захватить» текущее значение , равное i, вам необходимо создать новую область. Единственный способ сделать это в javascript - использовать другую функцию.

4 голосов
/ 09 марта 2010

Попробуйте:

var bongo = [];
for (i=0; i<10; i++) {
  $.get("http://localhost", function(result) {
    bongo.push(result);
  }
}

Таким образом, каждый результат будет просто помещен в массив, решая проблему правильности индексов массива. Заказ однако не гарантирован. Если это требование, вам понадобится другой подход.

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

function Callback(array, index, result) {
  this.array = array;
  this.index = index;
  this.result = result;
  var obj = this;
  this.func = function() {
    obj.array[obj.index] = obj.result;
  };
}

$(function() {
  var arr = [];
  for (var i=0; i<4; i++) {
    var obj = new Callback(arr, i, "result" + i);
    setTimeout(obj.func, (5-i) * 100);
  }
  setTimeout(function() {
    console.log(arr);
  }, 500);
});

Итак, в вашем случае:

function Callback(array, index) {
  this.array = array;
  this.index = index;
  var obj = this;
  this.callback = function(result) {
    obj.array[obj.index] = result;
  };
}

var bongo = [];
for (i=0; i<10; i++) {
  var ob = new Callback(bongo, i);
  $.get("http://localhost", ob.callback);
}

В основном вышесказанное сохраняет все данные в объект, и, таким образом, каждый обратный вызов имеет доступ к нужной информации.

Кроме того, имейте в виду, что большинство браузеров ограничивают количество одновременных запросов AJAX, обычно до 2 на хост.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...