Простой Ajax jQuery называет память утечек в Internet Explorer

Я создал веб-страницу, которая выполняет вызов Ajax каждую секунду. В Internet Explorer 7 это пропускает память плохо (20 МБ приблизительно за 15 минут).

Программа очень проста. Это просто выполняет функцию JavaScript, которая выполняет вызов Ajax. Сервер возвращает пустую строку, и код JavaScript ничего не делает с ним. Я использую setTimeout для выполнения функции каждую секунду, и я использую Каплю для наблюдения вещи.

Вот источник:


  
    
    
    
  
  
    Why is memory usage going up?
  

Как включить эту утечку? У меня есть реальное приложение, которое обновляет большую таблицу этот путь, но оставленный необслуживаемый он съест выше на гигабайты памяти.

Править: хорошо, поэтому после некоторых хороших предложений, я изменил код к:


  
    
    
    
  
  
    Why is memory usage going up?
  

Это, казалось, не имело значения, все же. Я ничего не делаю с DOM, и если я комментирую вызов Ajax, остановки утечки памяти. Таким образом, похоже, что утечка находится полностью в вызове Ajax. Ajax jQuery по сути создает своего рода циклическую ссылку, и если так, как я могу освободить его? Между прочим, это не протекает в Firefox.

Кто-то предложил запустить тест в другом VM, и посмотрите, является ли результатами то же. Вместо того, чтобы настраивать другой VM, я нашел ноутбук, который выполнял XP Домой с Internet Explorer 8. Это показывает ту же проблему.

Я попробовал некоторые более старые версии jQuery и получил лучшие результаты, но проблема не ушла полностью, пока я не отказался от Ajax в jQuery и пошел с более традиционным (и ужасный) Ajax.

40
задан Peter Mortensen 20 October 2010 в 09:27
поделиться

5 ответов

Проблема, похоже, связана с jQuery 1.4 в Internet Explorer и, в меньшей степени, версий 1.2 и 1.3.

В 1.4.0, 1.4.1 и 1.4.2 наблюдалась серьезная утечка памяти.

1.2.3, 1.2.6, 1.3.0, 1.3.1 и 1.3.2 показали гораздо меньшую утечку (около 100 КБ через 10 минут).

Я также пробовал версию моей программы, которая вызывает Ajax более традиционным способом:

<html>
  <head>
    <script language="javascript" type="text/javascript">
      function getHTTPObject() {
        var xmlhttp;
        /*@cc_on
        @if (@_jscript_version >= 5)
          try {
            xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
          } catch (e) {
            try {
              xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
            } catch (E) {
              xmlhttp = false;
            }
          }
        @else
        xmlhttp = false;
        @end @*/
        if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {
          try {
            xmlhttp = new XMLHttpRequest();
            if (xmlhttp.overrideMimeType) {
              xmlhttp.overrideMimeType("text/xml"); 
            }
          } catch (e) {
            xmlhttp = false;
          }
        }
        return xmlhttp;
      }
      var ajaxObject = getHTTPObject();
      setTimeout(testJunk,1000);
      function testJunk() {
        ajaxObject.open('POST', 'http://XXXXXXXXXXXXXXX/delme2', true);
        ajaxObject.onreadystatechange = handleAjaxResponse;
        ajaxObject.send(null);
      }
      function handleAjaxResponse() {
        if (ajaxObject.readyState==4) {
          setTimeout(testJunk,1000);
        }
      }
    </script>
  </head>
  <body>
    <div id="test">Why is memory usage going up?</div>
  </body>
</html>

Это полностью избавило от утечки.

Похоже, мне придется повторять вызовы Ajax старым уродливым способом, пока ребята из jQuery не решат эту проблему.

8
ответ дан 27 November 2019 в 01:54
поделиться

eval () наверняка съест память (eval происходит при передаче строки в setTimeout для оценки), не используйте его при тестировании :

setTimeout('testJunk()',1000);

должно быть:

setTimeout(testJunk, 1000);

Также лучше всего было бы использовать setInterval () для повторяющейся операции, как вы хотите, попробуйте следующее:

setInterval(testJunk, 1000);
5
ответ дан 27 November 2019 в 01:54
поделиться

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

function testJunk() {
    $.ajax({ url: 'http://xxxxxxxxxxxxxx/test', // The url returns an empty string
        dataType: 'html',
        complete: function(data){
            setTimeout(testJunk,1000);
        }
    });
}
testJunk();
0
ответ дан 27 November 2019 в 01:54
поделиться

Я столкнулся с той же проблемой и все утро был в тупике ... всего несколько минут назад. Проблема заключается в циклической ссылке, которая создается при установке обработчика onreadystatechange , что IE недостаточно умен, чтобы сломаться. Следовательно, решение состоит в том, чтобы явно нарушить его. Однако, очевидно, вы не можете сделать это из самого обработчика (хотя было бы удобно, если бы вы могли!).

Магический оператор:

delete request['onreadystatechange'];

Вам необходимо вести запись для каждого объекта XMLHttpRequest , для которого вы установили onreadystatechange . Затем, в какой-то момент после того, как readyState перейдет в 4, произведите магию над объектом. Если вы уже выполняете повторный опрос AJAX, логическим местом для проверки запросов на очистку будет тот же цикл опроса. Я определил простой объект RequestTracker для управления своими запросами.

Это сработало для меня; Я убедился, что утечка устранена. Вот, в частности, одна ссылка, которая проложила путь (я бы опубликовал больше, но StackOverflow мне не позволяет):

7
ответ дан 27 November 2019 в 01:54
поделиться

Вот ссылка на ошибку в jQuery, а также это предлагаемое исправление для jQuery 1.4.2:

--- jquery-1.4.2.js     2010-04-08 12:10:20.000000000 -0700
+++ jquery-1.4.2.js.fixed       2010-04-08 12:10:38.000000000 -0700
@@ -5219,7 +5219,7 @@

                            // Stop memory leaks
                            if ( s.async ) {
-                                       xhr = null;
+                                       xhr.onreadystatechange = null; xhr.abort = null; xhr = null;
                            }
                    }
            };

ПРИМЕЧАНИЕ : Это официально исправлено в jQuery 1.4.4, так что лучше всего просто обновить сейчас.

19
ответ дан 27 November 2019 в 01:54
поделиться
Другие вопросы по тегам:

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