Ошибка памяти DOM в IE8 (вставка большого количества данных JSON) - PullRequest
4 голосов
/ 31 марта 2010

Я разрабатываю небольшую веб-утилиту, которая отображает некоторые данные из некоторых таблиц базы данных.

У меня утилита работает нормально на FF, Safari, Chrome ..., но управление памятью в IE8 ужасно. Самый большой запрос JSON вернет информацию, чтобы создать около 5000 строк в таблице в браузере (3 столбца в таблице).

Я использую jQuery для получения данных (через getJSON). Чтобы удалить старую / существующую таблицу, я просто делаю $('#my_table_tbody').empty(). Чтобы добавить новую информацию в таблицу, в обратном вызове getJSON я просто добавляю каждую строку таблицы, которую я создаю, к переменной, а затем, как только они у меня есть, я использую $('#my_table_tbody').append(myVar), чтобы добавить ее к существующему телу. , Я не добавляю строки таблицы, поскольку они создаются, потому что это кажется намного медленнее, чем просто добавление их всех сразу. * +1007 *

Есть ли у кого-нибудь рекомендации о том, что должен делать кто-то, кто пытается добавить тысячи строк данных в DOM? Я хотел бы держаться подальше от нумерации страниц, но мне интересно, если у меня нет выбора.

Обновление 1 Вот код, который я пробовал после предложения innerHTML:

/* Assuming a div called 'main_area' holds the table */
document.getElementById('main_area').innerHTML = '';

$.getJSON("my_server", {my: JSON, args: are, in: here}, function(j) {
   var mylength = j.length;
   var k =0;
   var tmpText = '';
   tmpText += /* Add the table, thead stuff, and tbody tags here */;
   for (k = mylength - 1; k >= 0; k--)
   {
      /* stack overflow wont let me type greater than & less than signs here, so just assume that they are there. */
      tmpText += 'tr class="' + j[k].row_class . '"   td class="col1_class" ' + j[k].col1 + ' /td td class="col2_class" ' + j[k].col2 + ' /td  td class="col3_class" ' + j[k].col3 + ' /td /tr';
   }

   document.getElementById('main_area').innerHTML = tmpText;
}

В этом суть. Я также попытался использовать только запрос $ .get и заставить сервер отправлять отформатированный HTML, и просто установить его в innerHTML (т. Е. document.getElementById('main_area').innerHTML = j;).

Спасибо за все ответы. Я поражен тем фактом, что вы все готовы помочь.

Ответы [ 5 ]

2 голосов
/ 03 октября 2010
     var tmpText = [];
    for (k = mylength - 1; k >= 0; k--)
       {
          /* stack overflow wont let me type greater than & less than signs here, so just assume that they are there. */
    tmpText.push('anything you want')
          tmpText.push( 'tr class="' + j[k].row_class . '"   td class="col1_class" ' + j[k].col1 + ' /td td class="col2_class" ' + j[k].col2 + ' /td  td class="col3_class" ' + j[k].col3 + ' /td /tr';)
       }
    $('#main_area').html(tmpText.join(''))

    }

вам не нужно document.getElementById('main_area').innerHTML = '';

этот метод состоит в том, чтобы вставить в массив, затем присоединиться и использовать функцию hquml jquery для обновления. Это самый быстрый метод, который я знаю. Извините за формат здесь - это мой первый пост, и я подумал, что хочу вернуть что-то здесь в stackoverflow.

0 голосов
/ 14 августа 2010

Поскольку вы имеете дело с тысячами строк данных, я бы не назвал $('#my_table_tbody').empty() и не добавил бы новые данные с новыми элементами DOM. Вместо этого я бы следовал шаблону Object Pool . Таким образом, вместо того, чтобы отбрасывать все tr, вы можете повторно использовать существующие и просто заполнять новыми данными.

Если в вашем новом наборе данных меньше строк, чем в предыдущем, удалите оставшиеся строки из DOM, но сохраните ссылки на них в некотором пуле, чтобы сборщик мусора не уничтожил их. Если ваш новый набор данных больше - просто создайте новые tr по требованию.

Вы можете посмотреть на реализацию YUI DataTable , , вот источник. IIRC они используют этот подход, чтобы ускорить время рендеринга.

0 голосов
/ 31 марта 2010

Робусто прав в том, что назначение innerHTML - лучший путь. IE отстой при динамическом создании DOM

Почему бы не создать свой innerHTML на сервере, используя jsp, и передать его обратно через ajax за один прием Это определенно ускорит процесс, уберет сложность из вашего javascript и делегирует создание разметки на свое место.

0 голосов
/ 12 августа 2010

Как сказал Плоддер, у IE большие проблемы при работе с DOM. Лучшие практики jQuery рекомендуют создавать код в виде простой строки и добавлять его только один раз в контейнер.

Кроме этого, недавно у меня была похожая проблема для иерархических данных, имеющая 5000 записей данных. Я спросил себя: действительно ли пользователю нужна вся эта информация, доступная в данный момент? Затем я понял, что лучшее, что я мог сделать, это просто представить «первый кусок данных», а затем вставить дополнительные данные по запросу пользователя.

Наконец, только один хороший инструмент: Dynatrace Ajax (это очень помогает найти функцию javascript, для работы которой требуется больше времени)

0 голосов
/ 31 марта 2010

Чтобы IE быстро реагировал, вы должны создать строки таблицы в виде строковых представлений HTML, добавить их в строковую переменную и затем добавить результат в таблицу следующим образом.

myTable.myTbody.innerHTML = allThoseRowsAsAString;

Это не проблема памяти: 5000 строк должны быть тривиальными. Это должно быть намного меньше, чем один мегабайт.

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