jQuery: Проблема с заполнением массива при вызове $.getJSON

#javascript #jquery #arrays #couchdb

#javascript #jquery #массивы #couchdb

Вопрос:

Это код (см. КОД) Я использую, когда пытаюсь создать новый документ CouchDB. Документ содержит один или несколько существующих документов CouchDB (отслеживание истории). Результирующий json (см. JSON) для вновь созданного документа выглядит примерно так:

JSON:

{
  "_id": "b3360050039389801524044daf1c963c",
  "_rev": "1-2a5da40ce9a191b4decc27411ec9a181",
   "hodoc_type": "INCOMMING DELIVERY NOTE",
   "user_from": "ANS USER",
   "status": "INSTALLED ON SITE",
   "category": "ASET",
   "location": "MTX SPARE",
   "doctype": "hodoc",
   "items": [
     {
       "serial_number": "310310007590",
       "status": "STORED IN WAREHOUSE",
       "doctype": "data",
       "supplier": "INTRACOM",
       "po": "0",
       "category": "SPARE PART",
       "user_out": "IGOR JURUKOV",
       "mac": "NULL",
       "eqtype": "IDU",
       "location": "MTX SPARE",
       "location_comment": "NULL",
       "date_in": "2011-05-06",
       "date_out": "2011-05-06",
       "prf": "0",
       "part_number": "Z00-404/63.01",
       "user_in": "KOTE JANAKIEVSKI",
       "bar_code": "0",
       "manufacturer": "INTRACOM",
       "rma": "NULL",
       "product_name": "PSU for IDR-SM"
     },
     {
       "serial_number": "310407016955",
       "status": "STORED IN WAREHOUSE",
       "doctype": "data",
       "supplier": "INTRACOM",
       "po": "0",
       "category": "SPARE PART",
       "user_out": "IGOR JURUKOV",
       "mac": "NULL",
       "eqtype": "IDU",
       "location": "MTX SPARE",
       "location_comment": "NULL",
       "date_in": "2011-05-06",
       "date_out": "2011-05-06",
       "prf": "0",
       "part_number": "Z00-404/63.02",
       "user_in": "KOTE JANAKIEVSKI",
       "bar_code": "0",
       "manufacturer": "INTRACOM",
       "rma": "NULL",
       "product_name": "PSU for IDR-SM"
     }
   ]
}

код:

var docids = new Array();
var items = new Array();
$('div#divitemsout').find('img.item-out-remove').each(function () {
  var id = $(this).attr('attrid');
  if (docids.indexOf(id) == -1) {
    docids.push(docid);
  }
  var item = new Object;
  $.getJSON('/whdb/' id, function(data) {
    $.each(data, function(key, val) {
      if (key !== "_id" amp;amp; key !== "_rev") {
        item[key] = val;
      }
    });
    // Check No.1
    //alert(item.manufacturer);
  });
  // Check No.2
  //alert(item.manufacturer);
  items.push(item);
  });

Проблема и вопрос заключаются в следующем: когда выполняется приведенная ниже проверка строки №2, частью «items» результирующего документа json является [] . Когда приведенная ниже проверка № 2 предупреждения (item.manufacturer) не прокомментирована, я получаю предупреждения с содержимым «undefined», но часть «items» результирующего документа json установлена правильно, как показано в примере. Есть предложения?

Ответ №1:

Проблема просто во времени. Функция, которую вы передаете getJSON , не вызывается до тех пор, пока веб-сервер не вернет ответ на ваш запрос. So item не будет определено сразу после вызова getJSON . Добавление alert вызовов просто замедляет работу, так что у асинхронного вызова есть время для завершения.

Попробуйте переместить items.push(item) строку внутри getJSON обратного вызова.

Редактировать

Чтобы внести ясность, попробуйте это (в Chrome или Firefox с открытым Firebug, чтобы у вас была правильная console.log функция):

 var docids = new Array();
var items = new Array();
var waiting = 0;
$('div#divitemsout').find('img.item-out-remove').each(function () {
  var id = $(this).attr('attrid');
  if (docids.indexOf(id) == -1) {
    docids.push(docid);
  }
  var item = new Object;
  waiting  ;
  $.getJSON('/whdb/'   id, function(data) {
    waiting--;
    $.each(data, function(key, val) {
      if (key !== "_id" amp;amp; key !== "_rev") {
        item[key] = val;
      }
    });
    items.push(item);
    if(waiting == 0) {
      console.log('items:', items);
    }
  });
});
  

Комментарии:

1. Извините, Джорджджи, я вам не верю. Вы ждете, пока ваши getJSON методы обратного вызова сработают, прежде чем записывать содержимое вашего items массива?

2. Я не понимаю вопроса, но есть одна вещь, которую я должен сказать. Если я раскомментирую предупреждение при проверке № 1, я получу правильное значение для item.manufacturer, и items заполняется не так, как хотелось бы, независимо от того, находится оно внутри или вне кода getJSON. Если я раскомментирую предупреждение при проверке № 2, я получу «undefined» для item.manufacturer, и items в порядке, независимо от того, находится оно внутри или вне кода getJSON. Я попытался вызвать $.ajax(url, { async: false, … } с тем же успешным результатом.

3. @Gjorgji — вы должны получать ‘undefined’ для, item.manufacturer пока getJSON метод не будет запущен, что происходит после кода, который вы поставили на «Check No. 2» — то есть, как я уже упоминал, просто по времени. У вас есть две вещи, называемые «элементами» — переменная в коде и поле в документе JSON. Какой из них, вы имеете в виду, иногда является правильным? Откуда вы знаете — например, используете ли вы что-то вроде console.log("items: ", items) ? Можете ли вы показать свой метод проверки «элементов»?

4. элементы — это массив. Каждый элемент в массиве является объектом (item). Я проверяю выполнение кода с помощью оповещения (item.manufacturer). Проверка также может быть выполнена через item.product_name, item.serial_number и т.д. Я также использовал $(‘div#somedivid’).append(item.manufacturer ‘<br>’); но результаты были теми же.

5. @Gjorgji: Я отредактировал свой ответ, чтобы показать, как дождаться возврата всех асинхронных вызовов ajax, прежде чем печатать значение массива items.