Как избежать утечек памяти во время периодических запросов AJAX на IE9 - PullRequest
2 голосов
/ 07 марта 2012

Я разработал веб-страницу со статистикой.
Эта статистика периодически обновляется запросами AJAX с использованием mootools 1.4.5.

Вот основной код:

<script type="text/javascript">
   var statisticRequest = new Request.HTML({
      url: theURL,
      noCache: true,
      onSuccess: function(responseTree, responseElements, responseHTML, responseJavaScript) {
         $(responseTree[0]).replaces($('statisticContainer'))
      }
   })

   function getCurrentStatistics() {
      statisticRequest.get()
   }

   window.addEvent('domready', function(){
      getCurrentStatistics.periodical(2000)
   });
</script>

На FF все работает нормально, но IE9 постоянно выделяет память, пока машина почти не зависает. Похоже, сборщик мусора не удалил старые элементы DOM.

Используя sIEve , я вижу увеличивающееся количество элементов DOM и получающееся в результате использование памяти.

Что я могу сделать, чтобы заставить IE удалить неиспользуемые элементы?

Edit:

Использование destroy(), как показано ниже, замедлит потребление памяти, но не остановит его полностью. Удаление Request.HTML не имело дальнейшего эффекта.

<script type="text/javascript">
    var statisticRequest = new Request({
        url: theURL,
        noCache: true,
        onSuccess: function(responseText, responseXML) {
            var newStatistic = Elements.from(responseText)
            var oldStatistic = $('statisticContainer')
            newStatistic.replaces(oldStatistic)
            oldStatistic.destroy()
        }
    })

    function getCurrentStatistics() {
        statisticRequest.get()
    }

    window.addEvent('domready', function(){
        getCurrentStatistics.periodical(2000)
    });
</script>

Ответы [ 2 ]

1 голос
/ 07 марта 2012

да, вы можете. посмотрите на код для этого:

https://github.com/mootools/mootools-core/blob/master/Source/Element/Element.js#L743-747

он просто заменит его в доме. на самом деле это не будет иметь большого значения с точки зрения GC - старый элемент все еще «существует» - на случай, если вы захотите повторно присоединить его.

http://jsfiddle.net/rE3JH/

var foo = document.id('foo');
new Element('div').replaces(foo);
console.log(foo); // still an element, though not in the dom

вызовите foo.destroy(); для правильного сбора мусора - см. https://github.com/mootools/mootools-core/blob/master/Source/Element/Element.js#L802-807

альтернативно, обновите родительский элемент staticContainer - применив изменение к innerHTML direct. Кроме того, имейте в виду, что .empty() будет dispose дочерних узлов, а не destroy их - для таких периодических вещей, как ваша, вы должны быть внимательны, так как со временем они могут обрушиться.

0 голосов
/ 22 августа 2012

Я играл с этим некоторое время. Я думаю, что вам лучше использовать что-то вроде mootools. Это хорошо проверено и довольно мало. Он также предоставляет вам множество дополнительных функций, которые полностью совместимы с различными браузерами и не требуют расширенного тестирования.

Я выполняю следующий код более двух часов без утечек памяти. Надеюсь, что это поможет либо спрашивающему, либо кому-то другому, ищущему переполнение стека: Сначала файл index.html:

        <html>
            <head>
                <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
                <title>Untitled Document</title>
                <style>
                img.slide{
                    border:1px solid black;
                }
                </style>
                <script type="text/javascript" src="mootools/mootoolsCore.js">
                </script>
                <script type="text/javascript" src="mootools/mootoolsMore.js">
                </script>
                <script type="text/javascript">

        function data(){
            this.who="alan";
            this.pageHolder=1;
            this.lastPage = 4;
            this.count = 0;
        }

        var newData = new data();

        function changePage(newData,dirn){
            newData.dirn = dirn;
            saveData(newData);
        }

        function saveData(newData) {
            //alert("reached save data");
            var dataJSON = JSON.encode (newData);
            var request = new Request.JSON({
                method: 'post',
                url: 'forwardDataJson.php',
                data: {
                    json: dataJSON
                    },
                onComplete: function(jsonObj) {
                    newData.pageHolder = jsonObj.pageHolder;
                    newData.count = jsonObj.count;
                    $("picHolder").set('html','<img class="slide" src ="OpeningSlide/Slide'+jsonObj.pageHolder+'.jpg"/>');
                    $("alertBox").set('html',jsonObj.alertGiven);
                    $("countme").set('html',jsonObj.count);

                }
            }).send();
        };
        function getCurrentStatistics() {
              saveData(newData);
           }

           window.addEvent('domready', function(){
              getCurrentStatistics.periodical(2000)
           });

        </script>
            </head>
            <body>
                <div id="alertBox"></div>
                <button  type="button" onmousedown="changePage(newData,'backward')"/>backward</button>
                <button  type="button" onmousedown="changePage(newData,'forward')">forward</button>

                <div id="picHolder"><img class="slide" src ="OpeningSlide/Slide1.jpg"/></div>
                <div id="countme">0</div>

            </body>
        </html>

Это ищет серию изображений (Slide1.jpg, Slid2.jpg и т. Д.), А затем отображает их на странице. Он проверяет каждые две секунды новый бит информации и получает номер счетчика. Нажатие вперед или назад заставляет слайды проходить через каждые 2 секунды. Не очень интересно, но он демонстрирует принцип использования AJAX и опроса сервера с Mootools.

Вам также нужен скрипт на стороне сервера. Который в этом случае:

        <?php
        if(get_magic_quotes_gpc()){
            $test = stripslashes($_POST['json']);
        }else{
            $test = $_POST['json'];
        }
        $obj = json_decode($test);

        $direction = $obj->{'dirn'};
        $counter = $obj->{'count'};
        ++$counter;
        $obj->{'count'} = $counter;
        switch ($direction) {
            case "forward":
                if($obj->{'pageHolder'} < $obj->{'lastPage'}){
                    ++$obj->{'pageHolder'} ;
                }
                break;
            case "backward":
                if($obj->{'pageHolder'} >1){
                    --$obj->{'pageHolder'} ;
                }
                break;

        }


        $reply = json_encode($obj);

        echo $reply;
        ?>

Вы заметите, что я использовал JSON для передачи объекта на сервер и с сервера. Это просто для простоты кодирования. Если вы никогда не использовали его раньше, это путь (по крайней мере, на мой взгляд), поскольку его легко использовать, как только вы обдумаете это.

Этот пример должен работать как есть. Вам просто нужен каталог с именем OpeningSlide, который должен содержать ваши jpg слайды / изображения и, конечно, библиотеки mootools.

Надеюсь, это поможет

Кстати, если вам интересно узнать о первых нескольких строках php-кода, он поможет разобраться в проблемах с JSON и магическими кавычками. Он корректирует включение или отключение магических кавычек на сервере. Вы можете удалить его, если знаете настройки вашего сервера.

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