@Artemiy117

Как ускорить обработку элементов в массиве JS?

Подскажите, как можно оптимизировать код по загрузке ~5000 итемов?
Есть код:
console.time('create list');    
	var ch = '';            
            $.each(json.hotels, function(i) {

                // Если итем присутствует в GET запросе.
                if (qs && typeof qs.hotelId !=='undefined') {
                    ch = (qs.hotelId.length > 0 && $.inArray(json.hotels[i].id_extra, qs.hotelId) >= 0) ? true : false;
                } else ch = false;
                $("#st-all-hotels-list .st-listbox-content").append(checkableItem({
                    text: json.hotels[i].type + " " + json.hotels[i].name,
                    value: json.hotels[i].id_extra,
                    pans: json.hotels[i].pans_id,
                    star: json.hotels[i].star,
                    foh: true,
                    fohid: json.hotels[i].regionid,
                    ch: ch,
                    visible: true,
                    id: json.hotels[i].id,
                }));
                if (qs && typeof qs.hotelId !== 'undefined') {
                  
                  //alert(qs.hotelId.length +' : '+ json.hotels[i].id_extra +' : '+ qs.hotelId);
                  
                 if (qs.hotelId.length > 0 && $.inArray(json.hotels[i].id_extra, qs.hotelId) >= 0) {
                    $("#st-selected-hotels-list .st-listbox-content").append(clickableItem({
                            text: json.hotels[i].name,
                            value: json.hotels[i].id_extra
                    }));
                  }
                }
            });
console.timeEnd('create list');

function checkableItem(config) {
  
  var el = $('<div class="st-checkable-item" unselectable="on"><input type="checkbox" /><label unselectable="on"><span>' + config.text + '</span></label></div>')
  .mouseenter(function() {
      $(this).addClass('st-highlight');
  })
          .mouseleave(function() {
      $(this).removeClass('st-highlight');
  });

  var i = el.children('input');
  if (config.value !== undefined)
      i.val(config.value);
  
  i.attr('id','item_'+config.value);
  el.find('label').attr('for','item_'+config.value);
  
  if (config.pans)
      el.attr("pans", config.pans);
  if (config.star)
      el.attr('star', config.star);
  if (config.altValue)
      i.attr("data-altvalue", config.altValue);
  if (config.foh)
      el.attr('value', config.fohid);
  if (config.visible == false) {
      el.attr('style', 'display:none;');
  }
  if (config.ch) {
      el.addClass('st-checked');
      i.attr('checked', 'checked');
  }
  
  el.attr('my_type',config.visible);
  
  return el;
}

В итоге у меня формируется список из кликабельных отелей. Данные берутся из JSON файла. Но по времени это всё занимает полторы минуты. Что можно оптимизировать или переделать в коде чтобы побыстрее грузилось? Смотрел статью, но мало что подходит для конкретной ситуации.
PS: Пока идет загрузка, пользователю крутится loader. Но как только весь этот список итемов вываливается в DIV, loader останавливается, но не убирается. Висит все эти полторы секунды, потом пропадает. Хочется сократить это время.
  • Вопрос задан
  • 286 просмотров
Решения вопроса 2
@Maa-Kut
Как насчет того, чтобы не создавать/аппендить на каждой итерации новые элементы, а собирать вместо этого их в одну большую строку, которую затем разом положить в $("#st-selected-hotels-list .st-listbox-content")? Т.е. пусть checkableItem возвращает строку, а не элемент, и тогда будет что-то такое:
var str = '';

$.each(json.hotels, function(i) {
  str += checkableItem(...);
});

$("#st-all-hotels-list .st-listbox-content").append(str);

// Обработку событий из checkableItem убираем, навешиваем обработчики отдельно

$("#st-all-hotels-list .st-listbox-content").on('mouseenter', '.st-checkable-item', function() {
  $(this).addClass('st-highlight');
});

$("#st-all-hotels-list .st-listbox-content").on('mouseleave', '.st-checkable-item', function() {
  $(this).removeClass('st-highlight');
});
Ответ написан
Комментировать
trushka
@trushka
Каждый раз append() вызывает тормоза, да и функция checkableItem() тоже весьма рессурсоёмкая. Да и сам по себе вызов функции весьма притормаживает выполнение. То есть, лучше прописать прямо в коде. Причём, именно добавлять в текстовую переменную сгенерированный html. А ховер-эффект с помощью css :hover сделать (а так же для :checked, чтоб отдельного класса не прописывать, ну и там ещё какой-то аттрибут my_type задаётся и при этом display:none - так тоже можно прописать в css .st-checkable-item[my_type] {display:none}).
var ch = '', html='';            
            $.each(json.hotels, function(i) {

                // Если итем присутствует в GET запросе.
                ch =qs && qs.hotelId && qs.hotelId.length > 0 && $.inArray(json.hotels[i].id_extra, qs.hotelId) >= 0  // это выражение и так даст true или false
               html+='<div class="st-checkable-item" unselectable="on"><input id="item_'+config.value+'" type="checkbox" value="'+json.hotels[i].id_extra+'" data-altvalue="+config.altValue+'"'+(config.ch?' checked':'')+'><label for="item_'+config.value+'" unselectable="on"><span>' + json.hotels[i].type + "&nbsp;" + json.hotels[i].name + '</span></label></div>'
               // ну и т.д., я не все параметры тут вписал в код, но думаю, что ясно как остальные дописать.
            });
$("#st-all-hotels-list .st-listbox-content").append(html)
console.timeEnd('create list');
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@Artemiy117 Автор вопроса
Спасибо всем откликнувшимся, пока скрипт в работе. Какое из решений подошло - обязательно напишу. все работает. Сделал через строчку. Скорость выполнения скрипта сократилась до 60-90 мс. Лоадер чуток тупит все равно, но это наверно ему в другом месте что-то мешает.

Вопрос Maa-Kut: сохранятся ли атрибуты, если вываливать строкой итем? А то кликаться будет, а атрибутов не будет. Или их тоже можно просто в html описать?
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы